zoukankan      html  css  js  c++  java
  • Java集合 使用Set

    转载:https://www.liaoxuefeng.com/wiki/1252599548343744/1265121225603904

    我们知道,Map用于存储key-value的映射,对于充当key的对象,是不能重复的,并且,不但需要正确覆写equals()方法,还要正确覆写hashCode()方法。

    如果我们只需要存储不重复的key,并不需要存储映射的value,那么就可以使用Set

    Set用于存储不重复的元素集合,它主要提供以下几个方法:

    • 将元素添加进Set<E>boolean add(E e)
    • 将元素从Set<E>删除:boolean remove(Object e)
    • 判断是否包含元素:boolean contains(Object e)

    我们来看几个简单的例子:

    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            System.out.println(set.add("abc")); // true
            System.out.println(set.add("xyz")); // true
            System.out.println(set.add("xyz")); // false,添加失败,因为元素已存在
            System.out.println(set.contains("xyz")); // true,元素存在
            System.out.println(set.contains("XYZ")); // false,元素不存在
            System.out.println(set.remove("hello")); // false,删除失败,因为元素不存在
            System.out.println(set.size()); // 2,一共两个元素
        }
    }

    Set实际上相当于只存储key、不存储value的Map。我们经常用Set用于去除重复元素。

    因为放入Set的元素和Map的key类似,都要正确实现equals()hashCode()方法,否则该元素无法正确地放入Set

    最常用的Set实现类是HashSet,实际上,HashSet仅仅是对HashMap的一个简单封装,它的核心代码如下:

    public class HashSet<E> implements Set<E> {
        // 持有一个HashMap:
        private HashMap<E, Object> map = new HashMap<>();
    
        // 放入HashMap的value:
        private static final Object PRESENT = new Object();
    
        public boolean add(E e) {
            return map.put(e, PRESENT) == null;
        }
    
        public boolean contains(Object o) {
            return map.containsKey(o);
        }
    
        public boolean remove(Object o) {
            return map.remove(o) == PRESENT;
        }
    }

    Set接口并不保证有序,而SortedSet接口则保证元素是有序的:

    • HashSet是无序的,因为它实现了Set接口,并没有实现SortedSet接口;
    • TreeSet是有序的,因为它实现了SortedSet接口。

    用一张图表示:

           ┌───┐
           │Set│
           └───┘
             ▲
        ┌────┴─────┐
        │          │
    ┌───────┐ ┌─────────┐
    │HashSet│ │SortedSet│
    └───────┘ └─────────┘
                   ▲
                   │
              ┌─────────┐
              │ TreeSet │
              └─────────┘

    我们来看HashSet的输出:

    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            set.add("apple");
            set.add("banana");
            set.add("pear");
            set.add("orange");
            for (String s : set) {
                System.out.println(s);
            }
        }
    }

    注意输出的顺序既不是添加的顺序,也不是String排序的顺序,在不同版本的JDK中,这个顺序也可能是不同的。

    HashSet换成TreeSet,在遍历TreeSet时,输出就是有序的,这个顺序是元素的排序顺序:

    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Set<String> set = new TreeSet<>();
            set.add("apple");
            set.add("banana");
            set.add("pear");
            set.add("orange");
            for (String s : set) {
                System.out.println(s);
            }
        }
    }

    使用TreeSet和使用TreeMap的要求一样,添加的元素必须正确实现Comparable接口,如果没有实现Comparable接口,那么创建TreeSet时必须传入一个Comparator对象。

    小结

    Set用于存储不重复的元素集合:

    • 放入HashSet的元素与作为HashMap的key要求相同;
    • 放入TreeSet的元素与作为TreeMap的Key要求相同;

    利用Set可以去除重复元素;

    遍历SortedSet按照元素的排序顺序遍历,也可以自定义排序算法。

  • 相关阅读:
    积性函数前缀和
    CF1067D Computer Game
    Atcoder Tenka1 Programmer Contest 2019 题解
    Codeforces Round #549 (Div. 1) 题解
    SHOI2019旅游记
    CF871D Paths
    CF1065E Side Transmutations
    停更公告
    博客说明
    SCOI2019酱油记
  • 原文地址:https://www.cnblogs.com/shadoll/p/14385816.html
Copyright © 2011-2022 走看看