JavaSE 第七章集合 Collection

第七章集合Collection

在这里插入图片描述

7.1 Iterable 接口

首先是集合Collection的的爸爸,列表List的爷爷 Iterable接口。

实现此接口的类队形可以成为for-each循环的目标,也就是增强for循环,它是java中的一种语法糖。

List<Object> lists = new ArrayList<>();
for(Object obj : lists){
    
        }

jdk1.8之前集合的遍历只有Iteractor这一个方法 ,实现该次接口的方法能够创建一个轻量级的迭代器。用于安全的遍历元素,移除元素,添加元素。

总之就是能创建迭代器进行元素的添加和删除的话,就尽量使用迭代器。

也可以使用迭代器的方式进行遍历。

for (Iterator<Object> it = Collections.emptyIterator();it.hasNext();){
    
    
     System.out.println(it.next());
}

7.2 Collection 接口

Collection是一个顶级接口,用来定义集合的约定。

List 也是一个顶级接口,它继承了Collection接口,同时也是ArrayList、LinkedList等集合元素的父类。

Set接口位于List接口的同一层次,它也继承了Collection接口。Set接口提供了额外的规定,它对add、equals、hashcode方法提供了额外的标准。

Quene是和Set、List接口并列的Collection的三大接口之一。Quene的设计是用来保持元素的访问顺序。除了Collection接口提供的基础操作外,队列还提供了额外的插入、读取、检查操作。

public static void main(String[] args) {
    
    

        Collection c = new ArrayList();
        Collection c1 = new ArrayList();
        c1.add("c1");
        c1.add("c111");
        //增加
        c.add(1);
        c.add(2);
        c.add("s");
        c.add(true);
        //把另一个集合中的元素添加进来
        c.addAll(c1);
        System.out.println(c);

        //通过值来移除元素
        c.remove("c1");
        System.out.println("c = " + c);

        //是否有交集
        System.out.println(c.contains("c111"));

        //是否包含c1集合的全部元素
        c.add("c1");
        System.out.println(c.containsAll(c1));

        //从此集合中删除指定集合中不包含的所有元素。
        System.out.println(c.retainAll(c1));
        System.out.println("c = " + c);
    }

7.2.1 List<> 接口

ArrayList

ArrayList是实现了List接口的可扩容数组(动态数组,负载因子0.5)它的内部是基于数组实现的。

public class ArrayList<E>
    	extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  • ArrayList可以实现所有可选择的列表操作,允许所有的元素,包括空值。ArrayList还提供了内部存储list的方法,它能够完全替代Vector。

  • 只有一个例外,ArrayList不是线程安全的容器。如果多个线程中至少有两个线程修改了ArrayList的结构的话,就会导致线程安全问题。

  • 作为替代可以使用线程安全的List —— Collections.synchronizedList

  • ArrayList有一个容量的概念,这个数组的容量就是List用来存储元素的容量。

    List list = Collections.synchronizedList(new ArrayList(...));
    
  • ArrayList具有快速失败机制fail-fast,能够对ArrayList进行失败检测。当迭代过程中该集合在结构上发生变化时,就有可能会发生fail-fast,即抛出ConcurrentModificationException异常

常用方法

更多详细请去查阅Api文档

public class ArrayListDemo {
    
    

    public ArrayListDemo() {
    
    
    }

    public static void main(String[] args) {
    
    
        List list = new ArrayList<>();
        list.add("a");
        list.add("d");
        list.add("c");
        list.add("b");
        list.add("e");
        list.add("f");
        list.add(0,"g");
        list.remove(1);
        list.remove("d");
        //是否包含元素
        System.out.println(list.contains("f"));
        //获得元素的下标
        System.out.println(list.indexOf("e"));
        //过滤删除
        list.removeIf(new Predicate() {
    
    
            @Override
            public boolean test(Object o) {
    
    
                return o.equals("e");
            }
        });
        //更改下标处的元素
        list.set(1,"e");
        System.out.println(list.subList(0, 3));
        System.out.println(list);
    }

}

//removeRange() 只能被继承的子类使用
class ArrayListd extends ArrayList{
    
    
    public static void main(String[] args) {
    
    
        ArrayListd list = new ArrayListd();
        list.add("a");
        list.add("d");
        list.add("c");
        list.add("b");
        list.add("e");
        
        list.removeRange(1,3);
        System.out.println(list);
    }
}

Vector

Vector同ArrayList 一样,都是基于数组实现的,只不过Vector是一个线程安全的容器,它对内部的每个方法都简单粗暴的上锁,避免多线程引起的安全性问题,但是通常这种同步方式需要的开销比较大,因此,访问元素的效率要远远低于ArrayList。
还有一点在于扩容上,ArrayList扩容后的数组长度会增加50%,而Vector的扩容长度后数组会增加一倍(负载因子为1)

常用方法

更多详细请去查阅Api文档

public class VectorDemo {
    
    

    public VectorDemo() {
    
    
    }

    public static void main(String[] args) {
    
    
        /*
            和ArrayList不同的是 : Vector是线程安全的数组
         */
        Vector v = new Vector();
        v.add(1);
        v.add(2);
        v.add(3);
        v.add(1);
        v.add(4);

        System.out.println(v);
    }
}
LinkedList

LinkedList是一个双向链表,允许存储任何元素(包括null值)

  • LinkedList所有的操作都可以表现为双向性的,索引到链表的操作将遍历从头到尾,视哪个距离近为遍历顺序

  • 该LinkedList实现链表也不是线程安全的,==如果多线程并发访问链表,并且其中一个线程修改了链表的结构,那么这个链表必须进行外部加锁。==或者使用:

    List list = Collections.synchronizedList(new LinkedList());
    
常用方法

更多详细请去查阅Api文档

public class LinkedListDemo {
    
    
    public LinkedListDemo() {
    
     }
    public static void main(String[] args) {
    
    
        LinkedList list = new LinkedList();
        list.add("a");
        list.add("d");
        list.add("c");
        list.add("b");
        list.add("e");

        list.addFirst("k");
        list.addLast("k1");

        list.remove(2);
        list.removeFirst();
        list.removeLast();

        list.get(3);
        list.getFirst();
        list.getLast();
    }
}

Stack

堆栈是后入先出的容器。它继承了Vector类,提供了通用的push和pop操作,以及栈顶的peek方法,测试栈是否为空的isEmpty方法,和一个寻找与栈顶距离的search方法。

第一次创建栈,不包含任何元素。

一个更完善,可靠性更强的LIFO栈操作由Deque接口和他的实现提供。官方建议应该优先使用这个类。

Deque<Integer> stack = new ArrayDeque<Integer>()

7.2.2 Set<> 接口

HashSet

HashSet是Set接口的实现类,由哈希表支持(实际上HashSet是HashMap(负载因子为0.75)的一个实例)。它不能保证集合的迭代顺序。这个类允许null元素。

  • ==该实现类不是线程安全的。如果多线程并发访问Set,并且至少有一个线程修改了set,则必须进行外部加锁。或使用Collections.synchronizedSet()==方法
  • 该实现支持fail-fast机制。
常用方法

更多详细请去查阅Api文档

public class HashSetDemo {
    
    
    public HashSetDemo() {
    
     }
    public static void main(String[] args) {
    
    
        /*
            Set 不允许重复元素
                HashSet  无序(底层是有一定的规则的)
                TreeSet  有序
        */
        HashSet<String> stringSet = new HashSet<>();
        stringSet.add("a");
        stringSet.add("a");
        stringSet.add("中暑");
        stringSet.add("b");
        stringSet.add("田");
        /*
            调用hash()方法, 效率高  但是可能会有重复的hash值,所以不安全
            再使用equals()    安全性高
         */
        System.out.println("stringSet = " + stringSet);

        HashSet<Student> studentSet = new HashSet<>();

        studentSet.add(new Student(101,"jim"));
        studentSet.add(new Student(102,"jim1"));
        studentSet.add(new Student(103,"jim2"));
        studentSet.add(new Student(104,"jim3"));
        studentSet.add(new Student(101,"jim"));

        System.out.println(studentSet);
    }
}

TreeSet

TreeSet是基于TreeMap的NavigableSet实现的。==这些元素使用他们的自然排序或者在创建时提供的Comparactor进行排序,==具体取决于使用的构造函数

  • 此实现为基本操作add、remove和contains提供了log(n)的时间成本。

  • 该实现也不是线程安全的,==如果有多个线程并发访问,并且至少有一个线程修改了TreeSet,则必须进行外部加锁。==或使用:

    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...)) 
    
  • 该实现也支持fail-fast机制

常用方法

更多详细请去查阅Api文档

public class TreeSetDemo {
    
    

    public TreeSetDemo() {
    
    
    }

    public static void main(String[] args) {
    
    
        TreeSet<String> strTree = new TreeSet<>();
        strTree.add("e");
        strTree.add("a");
        strTree.add("c");
        strTree.add("b");
        strTree.add("f");
        strTree.add("d");
        strTree.add("a");
        System.out.println("strTree = " + strTree);

        /*
            TreeSet  元素不可重复
                    有序   指定类必须要实现 Comparable中的compareTo方法

         */
        TreeSet<Student> treeStudent = new TreeSet<>();

        treeStudent.add(new Student(101,"jim"));
        treeStudent.add(new Student(102,"jim1"));
        treeStudent.add(new Student(104,"jim3"));
        treeStudent.add(new Student(105,"jim2"));
        treeStudent.add(new Student(101,"jim"));

        System.out.println(treeStudent);
    }
}
          //Compartor   比较器

                  //Comparable 实现该接口才有排序能力
public class Student implements Comparable<Student>{
    
    
    int num;
    String name;
    public Student() {
    
     }

    public Student(int num, String name) {
    
    
        this.num = num;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return num == student.num &&
                name.equals(student.name);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(num, name);
    }

    @Override
    public int compareTo(@NotNull Student o) {
    
    
        //return this.num - o.num;
        return this.name.compareTo(o.name);
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "num=" + num +
                ", name='" + name + '\'' +
                '}';
    }
}

LinkedHashSet

LinkedHashSet是Set接口的Hash表和LinkedList的实现,该实现不同于HashSet的是它是一个贯穿所有元素的双向链表。此链表定义了元素插入集合的顺序。

注意:如果元素重新插入,则插入的顺序不受影响。

  • LinkedHashSet有两个影响其构成的参数︰初始容量和加载因子。它们的定义与HashSet 完全相同。但请注意: 对于LinkedHashSet,选择过高的初始容量值的开销要比 HashSet小,因为LinkedHashSet的迭代次数不受容量影响。
  • LinkedHashSet也不是线程安全的,如果多线程并发访问LinkedHashSet,必须加锁,或使用Collections.synchronizedSet
  • 该实现也支持fail-fast机制

7.3 Map<> 接口

7.3.1 HashMap

==HashMap是一个利用Hash表原理来存储元素的集合。==并且允许空的键值对。HashMap是非线程安全的,也就是说在多线程环境下可能会出现一些问题。而Hashtable是线程安全的容器。

HashMap 的实例有两个参数影响其性能︰初始容量和加载因子。可以使用Collections.synchronizedMap(new HashMap(…))来构造一个线程安全的 HashMap。

  • 该实现也支持fail-fast机制
遍历方法
Set<Map.Entry<Integer, String>> entries = map.entrySet();
        for(Map.Entry entry : entries){
    
    
            System.out.println(entry.getKey()+"="+entry.getValue());
        }

7.3.2 TreeMap

==一个基于NavigableMap实现的红黑树。==这个map是根据自然排序存储,或者通过Compartor进行定制排序。

  • TreeMap为containsKey、get、put和remove方法提供了log(n)的时间开销。

  • 注意这个实现不是线程安全的。如果多线程并发访问TreeMap,并且至少一个线程修改了map,必须进行外部加锁。这通常通过在自然封装集合的某个对象上进行同步来实现,或者使用:

    SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...))
    
  • 该实现也支持fail-fast机制

7.3.3 LinkedHashMap

==LinkedHashMap是Map 接口的哈希表和链表的实现。这个实现与HashMap 不同之处在于它维护了一个贯穿其所有条目的双向链表。==这个链表定义了遍历顺序,通常是插入map 中的顺序。

  • 它提供一个特殊的LinkedHashMap(int,float, boolean)构造器来创建LinkedHashMap,其遍历顺序是其最后一次访问的顺序。

  • 可以重写 removeEldestEntry(Map.Entry)方法,以便在将新映射添加到map时强制删除过期映射的策略。

  • 这个类提供了所有可选择的map操作,并且允许null元素。由于维护链表的额外开销,性能可能会低于HashMap,有一条除外︰遍历LinkedHashMap 中的collection-views 需要与map.size成正比,无论其容量如何。HashMap的迭代看起来开销更大,因为还要求时间与其容量成正比。

  • LinkedHashMap有两个因素影响了它的构成∶初始容量和加载因子。

  • 注意这个实现不是线程安全的。如果多线程并发访问LinkedHashMap,并且至少一个线程修改了map,必须进行外部加锁。这通常通过在自然封装集合的某个对象上进行同步来实现,或使用:

    Map m =Collections.synchronizedMap(new LinkedHashMap( . .. ))
    
  • 这个实现持有fail-fast机制。

7.3.4 Hashtable

Hashtable类实现了一个哈希表,能够将键映射到值。任何非空对象都可以用作键或值。

  • 此实现类支持fail-fast 机制
  • 与新的集合实现不同,Hashtable是线程安全的。如果不需要线程安全的容器,推荐使用HashMap如果需要多线程高并发,推荐使用ConcurrentHashMap 。

7.3.5 WeakHashMap

WeakHashMap类基于哈希表的Map基础实现,带有弱键。WeakHashMap 中的entry当不再使用时还会自动移除。更准确的说,给定key的映射的存在将不会阻止 key被垃圾收集器丢弃。

  • 基于map 接口,是一种弱键相连, WeakHashMap 里面的键会自动回收
  • 支持null值和null键。
  • fast-fail 机制
  • 不允许重复
  • WeakHashMap 经常用作缓存

7.4 Collections 工具类

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37079157/article/details/110821509
今日推荐