Set

java.util.Set 接口和 java.util.List 接口一样,同样继承自 Collection 接口,它与 Collection 接口中的方法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比 Collection 接口更加严格了。

public interface Set<E> extends Collection<E> {

    A:添加功能
    boolean add(E e);
    boolean addAll(Collection<? extends E> c);

    B:删除功能
    boolean remove(Object o);
    boolean removeAll(Collection<?> c);
    void clear();

    C:长度功能
    int size();

    D:判断功能
    boolean isEmpty();
    boolean contains(Object o);
    boolean containsAll(Collection<?> c);
    boolean retainAll(Collection<?> c); 

    E:获取Set集合的迭代器:
    Iterator<E> iterator();

    F:把集合转换成数组
    Object[] toArray();
    <T> T[] toArray(T[] a);

    //判断元素是否重复,为子类提高重写方法
    boolean equals(Object o);
    int hashCode();
}

与 List 接口不同的是, Set 接口中元素无序,并且都会以某种规则(提供equals(Object o)和hashCode(),供其子类重写)保证存入的元素不出现重复。

Set 集合常用的子类: java.util.HashSet 、 java.util.LinkedHashSet

Set集合取出元素的方式可以采用:迭代器、增强for。

 

HashSet 

public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable

HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,存取、查找效率高。

HashSet 底层的实现是一个 java.util.HashMap(即存储数据的结构是——哈希表),利用HashMap键(key)来存储元素,计算插入元素的hashCode来获取元素在集合中的位置;。

而保证元素唯一性的方式依赖于: hashCode 与 equals 方法。

哈希表在Map笔记中具体介绍。 

 

HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方 式,才能保证HashSet集合中的对象唯一

 

HashSet方法

public class HashSetTest {
    public static void main(String[] agrs){
        //创建HashSet集合:
        Set<String> hashSet = new HashSet<String>();
        System.out.println("HashSet初始容量大小:"+hashSet.size());

        //元素添加:
        hashSet.add("Hello");
        hashSet.add("World");
        hashSet.add("!");
        System.out.println("HashSet容量大小:"+hashSet.size());

        // 迭代器遍历:
        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
        // 增强for循环
        for(String str:hashSet){
            if("World".equals(str)){
                System.out.println("查找的元素:"+str);
            }
            System.out.println(str);
        }

        // 元素删除:
        hashSet.remove("World");
        System.out.println("HashSet元素大小:" + hashSet.size());
        hashSet.clear();
        System.out.println("HashSet元素大小:" + hashSet.size());

        //集合判断:
        boolean isEmpty = hashSet.isEmpty();
        System.out.println("HashSet是否为空:" + isEmpty);
        boolean isContains = hashSet.contains("hello");
        System.out.println("HashSet是否为空:" + isContains);
    }
}

 

LinkedHashSet

public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, Serializable

java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构,元素唯一且有序

 

TreeSet

public class TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable

其底层实现为:红黑树(特殊的二叉查找树)

TreeSet具有排序功能,分为自然排序(123456)和自定义排序两类,默认是自然排序

 

HashSet 和 TreeSet 特点

HashSet TreeSet 
元素不重复 元素不重复
元素无序(存取顺序不一样) 元素有序(会对插入的元素进行排序)
允许插入null值 允许插入null值
线程不安全(多线程操作,需手动实现同步) 线程不安全(多线程操作,需手动实现同步)

 

TreeSet方法

public class TreeSetTest {
    public static void main(String[] agrs){
        TreeSet<String> treeSet = new TreeSet<String>();
        System.out.println("TreeSet初始化容量大小:"+treeSet.size());

        //元素添加:
        treeSet.add("hello");
        treeSet.add("world");
        treeSet.add("flower");
        treeSet.add("water");
        treeSet.add("grass");
        System.out.println("TreeSet容量大小:" + treeSet.size());
        System.out.println("TreeSet元素顺序为:" + treeSet.toString());

        //增加for循环遍历:
        for(String str:treeSet){
            System.out.println("遍历元素:"+str);
        }

        //迭代器遍历:升序
        Iterator<String> iteratorAesc = treeSet.iterator();
        while(iteratorAesc.hasNext()){
            String str = iteratorAesc.next();
            System.out.println("遍历元素升序:"+str);
        }

        //迭代器遍历:降序
        Iterator<String> iteratorDesc = treeSet.descendingIterator();
        while(iteratorDesc.hasNext()){
            String str = iteratorDesc.next();
            System.out.println("遍历元素降序:"+str);
        }

        //元素获取:实现NavigableSet接口
        String firstEle = treeSet.first();//获取TreeSet头节点:
        System.out.println("TreeSet头节点为:" + firstEle);

        // 获取指定元素之前的所有元素集合:(不包含指定元素)
        SortedSet<String> headSet = treeSet.headSet("flower");
        System.out.println("flower节点之前的元素为:"+headSet.toString());

        //获取给定元素之间的集合:(包头,不包尾)
        SortedSet subSet = treeSet.subSet("1","world");
        System.out.println("1--jiaboan之间节点元素为:"+subSet.toString());

        //集合判断:
        boolean isEmpty = treeSet.isEmpty();
        System.out.println("TreeSet是否为空:"+isEmpty);
        boolean isContain = treeSet.contains("light");
        System.out.println("TreeSet是否包含light元素:"+isContain);

        //元素删除:
        boolean removeG = treeSet.remove("grass");
        System.out.println("grass元素是否被删除:"+removeG);

        //删除集合中不存在的元素,返回false
        boolean removeL = treeSet.remove("light");
        System.out.println("light元素是否被删除:"+removeL);

       //删除并返回第一个元素:如果set集合不存在元素,则返回null
        String pollFirst = treeSet.pollFirst();
        System.out.println("删除的第一个元素:"+pollFirst);

        //删除并返回最后一个元素:如果set集合不存在元素,则返回null
        String pollLast = treeSet.pollLast();
        System.out.println("删除的最后一个元素:"+pollLast);

        treeSet.clear();//清空集合:
    }
}

 

TreeSet自然排序

使用String、Integer等包装类型(JDK的内置对象),数据可以通过add方法添加到TreeSet集合中。

 

TreeSet自定义排序

使用自定义类型时,add方法会报错,抛出异常:

Exception in thread "main" java.lang.ClassCastException: com.**.ClassName cannot be cast to java.lang.Comparable

是因为,TreeSet的add()方法调用的时TreeMap的put()方法,

在put方法中会调用到compare(key, key)方法,进行key大小的比较(排序在此时实现)

在比较的时候,会将传入的key进行类型强转,自定义类如果没有实现Comparable接口,就会如上。

Comparable和Comparator单独说明。

 

 

参考引用:

https://www.jianshu.com/p/d6cff3517688

 posted on 2021-03-09 21:25  一计  阅读(46)  评论(0)    收藏  举报