总结:Java的集合框架

一、前言



Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。

在jdk1.2之前,Java就提供了诸如:Dictionary, Vector, Stack,这些类用来存储和操作对象组。但是它们缺少一个统一的主题。于是在jdk1.2之后便出现了集合框架,在jdk1.5上又添加了Iterable接口用来实现集合的迭代, 整个集合框架就围绕一组标准接口(例如Set,List) 而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet等,除此之外你也可以通过这些接口实现自己的集合。

读者还应注意Java中集合与数组的区别:

  1. 已定义集合的大小可变,而已定义的数组大小不可变(注意:集合内部实现机制也用到了对象数组,只是通过数组的复制或链式存储的方式使其从外部看起来是可变的,而其本身并未颠覆数组大小不可变这一观点)
  2. 数组可以存储基本数据类型和引用类型,而集合只能存储引用类型,例如传入add方法中的int会被自动封装成Integer类型
  3. 数组只能存储相同类型的数据,而集合如未确定泛型的具体类型,则可存储任意引用类型数据

二、集合类图概述:

(注:1.此图只显示类常用接口和类,省略了部分中间类,将在下文逐一说明。2.Map族独立于collection,但属于集合框架中的一部分)

接口及类的详解:

1.Iterator<E>接口

首先要注意一点, Iterator接口和Iterable接口没有半毛钱的继承实现关系 ,唯一的关系是,在Iterable接口中有一个可返回Iterator类型的方法iterator()。 Iterator是一个集合的迭代器,通俗的说,它可将集合中的元素逐次取出,常用方法如下:

boolean hasNext() 如果还可以迭代下一个元素,则返回true
E next() 返回迭代中的下一个元素

2.Iterable接口

Collection族下的类都间接实现此接口,实现此接口允许对象成为“for-each loop”语句的目标

接口中两个最常用的方法如下:

default void forEach(Consumer<? super T> action 对 Iterable 的每个迭代元素执行给定的操作,传入一个函数的引用
Iterator<T> iterator() 返回类型为 T 的迭代器

代码示例:

 
  1. public static void main (String[] args) {
  2. ArrayList arrayList= new ArrayList();
  3. arrayList.add( 520 );
  4. arrayList.add( true );
  5. arrayList.add( new Date());
  6. arrayList.forEach(System.out::println);
  7. Iterator iterator=arrayList.iterator();
  8. while (iterator.hasNext()){
  9. System.out.println(iterator.next());
  10. }
  11. }

运行结果:

3.Collection接口

集合层次结构中的根接口 。 集合表示一组被称为其 元素 的对象。 一些集合允许重复元素,而其他集合不允许。JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List 等,常用扩展方法如下:

boolean add(E e) 添加元素
boolean addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到该集合中
void clear() 删除此集合中的所有元素
boolean contains(Object o) 判断此集合是否包含指定元素,对比方式是equals(Object o)
boolean isEmpty() 判断集合是否为空
boolean remove(Object o) 成功返回true,如果删除失败或者该元素不存在,返回false
boolean removeAll(Collection<?> c) 删除本集合中与给定集合的交集
boolean retainAll(Collection<?> c) 保存本集合中与给定集合的交集
int size() 返回此集合中的元素数
Object[] toArray() 返回一个包含此集合中所有元素的对象数组

4.List接口及其实现类

首先说明List与Set的区别:

List Set
元素有序(存入取出位置不变) 元素无序
元素存在唯一的索引值 不存在索引
允许重复元素 不允许重复元素

在Collection基础上,List扩展的如下方法:

void add(int index,E element) 将元素插入指定的位置
boolean addAll(int index,Collection<? extend E> c) 按指定集合的迭代器顺序将其添加到本元素的指定位置
E get(int index) 返回此列表指定位置的元素

int indexOf(Object o)

int lastIndexOf(Object o)

返回此列表中指定元素第一次(最后一次)出现的位置

如果不存在则返回-1

ListIterator<E> listiterator()

ListIterator<E> listiterator(int index)

返回此列表中的列表迭代器

从指定位置开始返回迭代器

E remove(int index) 删除指定位置的元素,并返回到该元素
default void sort(Comparator<? super E> c) 使用随附的 Comparator排序此列表来比较元素。
List<E> subList(int fromIndex, int toIndex) 返回此列表中指定的 fromIndex (含)和 toIndex之间的视图。

注:ListIterator 接口继承自 Iterator,它允许沿任一方向遍历列表

代码示例:

 
  1. public static void main (String[] args) {
  2. ArrayList arrayList= new ArrayList();
  3. arrayList.add( 520 );
  4. arrayList.add( 43 );
  5. arrayList.add( 321 );
  6. arrayList.add( 0 , 999 );
  7. arrayList.add( 334 );
  8. System.out.println( "原始数组:" );
  9. arrayList.forEach(System.out::println);
  10. System.out.println( "获取第3个元素:" +arrayList.get( 2 ));
  11. System.out.println( "a的位置:" +arrayList.indexOf( 520 ));
  12. System.out.println( "排序后:" );
  13. arrayList.sort(Comparator.comparing(Integer::intValue));
  14. arrayList.forEach(System.out::println);
  15. System.out.println( "ListIterator迭代:" );
  16. ListIterator listIterator=arrayList.listIterator();
  17. while (listIterator.hasNext()){
  18. System.out.println(listIterator.next());
  19. }
  20. System.out.println( "删除第3个位置的元素:" +arrayList.remove( 2 ));
  21. System.out.println( "新建数组内容为" );
  22. List list=arrayList.subList( 1 , 3 );
  23. list.forEach(System.out::println);
  24. }

运行结果:

一.ArrayList 类

实现List接口,并允许所有元素,包括null,每个ArrayList实例都有一个容量 。 容量是用于存储列表中的元素的数组的大小。 它总是至少与列表大小一样大。 当元素添加到ArrayList时,其容量会自动增长。 没有规定增长的细节

此处说明:

ArrrayList与Vector的区别:1.ArrayList不是线程同步的,而Vector是线程同步的。2.ArrayList默认扩容量是原来的0.5倍,而Vector的默认扩容是原来的一倍

ArrayList与LinkedList的区别:ArrayList由数组备份。LinkedList由链接备份,并且LinkedList还可以用作队列。访问ArrayList中的元素更快,因为它的底层结构是数组,而当集合要频繁的进行增删,LinkedList 的性能优于 ArrayList 。

继承关系:

构造方法:

ArrayList() 构造一个初始容量为十的空列表。
ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。

扩展方法:

Object clone() 返回此 ArrayList实例的浅拷贝(关于深浅拷贝的区别见下文)
void ensureCapacity(int minCapacity) 增加此 ArrayList实例的容量,以确保它可以至少保存最小容量参数指定的元素数
void trimToSize() 修改这个 ArrayList实例的容量是列表的当前大小
void replaceAll(UnaryOperator<E> operator) 将该列表的每个元素替换为将该运算符应用于该元素的结果
E set(int index, E element) 用指定的元素替换此列表中指定位置的元素

注:浅拷贝:被复制对象与原对象在内存中的引用是同一个对象

深拷贝:在内存中新开辟一块空间,把要复制的对象所引用的对象都复制了一遍,对现在对象的修改不会影响原有的对象。

代码示例:

 
  1. public class Main {
  2. public static void main (String[] args) {
  3. ArrayList arrayList = new ArrayList( 100 );
  4. People people1 = new People( 66 );
  5. arrayList.add(people1);
  6. arrayList.add( new People( 47 ));
  7. arrayList.add( new People( 33 ));
  8. arrayList.set( 2 , new People( 55 ));
  9. people1.setAge( 100 );
  10. arrayList.forEach(System.out::println);
  11. System.out.println( "拷贝数组" );
  12. ArrayList clonearray = (ArrayList) arrayList.clone();
  13. clonearray.forEach(System.out::println);
  14. System.out.println( "将people的值改变后:" );
  15. people1.setAge( 888 );
  16. clonearray.forEach(System.out::println);
  17. }
  18. }
  19. class People {
  20. int age;
  21. public People ( int age) {
  22. this .age = age;
  23. }
  24. public int getAge () {
  25. return age;
  26. }
  27. public void setAge ( int age) {
  28. this .age = age;
  29. }
  30. @Override
  31. public String toString () {
  32. return "People{" +
  33. "age=" + age +
  34. '}' ;
  35. }
  36. }

运行结果:

二.LinkedList类

LinkedList是非线程同步的,LinkedList与ArrayList的区别上文已讲,而当集合要频繁的进行增删,建议使用LinkedList提高性能,由于LinkeList还是同时实现了List和Deque接口,所以它还可以用来表示队列 ,具体实现在下文Queue接口和Deque接口中

类图结构:

三.Vector类

Vector在共功能上与ArrayList相似,如果不需要线程安全的实现,建议使用ArrayList代替Vector

构造方法如下:

Vector() 构造一个空向量,使其内部数据数组的大小为 10 ,标准容量增量为零
Vector(Collection<? extends E> c) 构造一个包含指定集合元素的向量,按照集合的迭代器返回的顺序。
Vector(int initialCapacity) 构造具有指定初始容量并且其容量增量等于零的空向量。
Vector(int initialCapacity, int capacityIncrement) 构造具有指定的初始容量和容量增量的空向量。

成员方法略

四.Stack类

Stack是一个后进先出的栈(LIFO),但Deque接口及其实现提供了更完整和一致的LIFO堆栈操作集,这些接口应优先于此类。 例如: Deque<Integer> stack = new ArrayDeque<Integer>();

Stack继承自Vector,扩展方法如下:

boolean empty() 测试此堆栈是否为空。
E peek() 查看此堆栈顶部的对象,而不从堆栈中删除它。
E pop() 删除此堆栈顶部的对象,并将该对象作为此函数的值返回。
E push(E item) 将项目推送到此堆栈的顶部。
int search(Object o) 返回一个对象在此堆栈上的基于1的位置

代码示例:

 
  1. private static void showpush (Stack st, int a) { //把项压入栈顶
  2. st.push( new Integer(a));
  3. System.out.println( "push(" + a + ")" );
  4. System.out.println( "stack: " + st);
  5. }
  6. private static void showpop (Stack st) { //移除堆栈顶部的对象并作为此函数的值返回该对象
  7. Integer a = (Integer) st.pop();
  8. System.out.println(a);
  9. System.out.println( "after pop stack: " + st);
  10. }
  11. private static void showpeek (Stack stack) {
  12. Integer a=(Integer) stack.peek();
  13. System.out.println(a);
  14. System.out.println( "after peek stack:" +stack);
  15. }
  16. public static void main (String args[]) {
  17. Stack st = new Stack();
  18. System.out.println( "stack: " + st);
  19. showpush(st, 42 );
  20. showpush(st, 66 );
  21. showpush(st, 99 );
  22. showpeek(st);
  23. showpop(st);
  24. showpop(st);
  25. showpop(st);
  26. try {
  27. showpop(st);
  28. } catch (EmptyStackException e) {
  29. System.out.println( "empty stack" );
  30. }
  31. }

运行结果:

5.Set接口及其实现类

Set集合是唯一元素集合,最多只有一个null值,当向集合添加重复元素时,它们将被忽略,元素是否相同是通过equals()方法实现的

一.HashSet和LinkedHashSet

区别: HashSet 不保证顺序元素。 LinkedHashSet 在插入元素时保持元素顺序

代码示例:

 
  1. public static void main (String[] args) {
  2. Set hashSet= new HashSet();
  3. hashSet.add( "XML" );
  4. hashSet.add( "HTML" );
  5. hashSet.add( "SQL" );
  6. hashSet.add( null );
  7. hashSet.add( "HTML" );
  8. hashSet.add( null );
  9. hashSet.add( "JAVA" );
  10. System.out.println( "hashSet:" +hashSet);
  11. HashSet linkHashSet= new LinkedHashSet<>();
  12. linkHashSet.add( "XML" );
  13. linkHashSet.add( "HTML" );
  14. linkHashSet.add( "SQL" );
  15. linkHashSet.add( null );
  16. linkHashSet.add( "HTML" );
  17. linkHashSet.add( null );
  18. linkHashSet.add( "JAVA" );
  19. System.out.println( "LinkedHashSet:" +linkHashSet);
  20. }

运行结果:

二.TreeSet类

SortedSet 接口表示Java集合中的排序集合框架,如果它的元素实现了Comparable接口,它将使用compareTo()方法来排序项目。 我们可以称之为自然顺序排序。我们也可以传递一个比较器Comparator做自定义排序。如果指定了 Comparator ,则将Comparator 用于排序并忽略 Comparable 接口。
TreeSet 类是Collection框架中SortedSet接口的一个实现。

类图结构:

代码示例:

 
  1. public class Main {
  2. public static void main (String[] args) {
  3. /* 按照String中的compareTo的默认比较方法
  4. 先比较字符串长度,如果长度一样,则按照字典的顺序依次比较,小写大于大写*/
  5. SortedSet sortedSet= new TreeSet();
  6. sortedSet.add( "jav" );
  7. sortedSet.add( "hdTM" );
  8. sortedSet.add( "xML" );
  9. sortedSet.add( "sQL" );
  10. System.out.println(sortedSet);
  11. /*
  12. 使用Comparable比较器自定义排序关键字
  13. */
  14. SortedSet<Student> students= new TreeSet<>(Comparator.comparing(Student::getAge));
  15. students.add( new Student( "Kangkang" , 13 ));
  16. students.add( new Student( "Mike" , 11 ));
  17. students.add( new Student( "Jack" , 18 ));
  18. students.add( new Student( "Lihua" , 14 ));
  19. System.out.println( "将学生按年龄排序:" );
  20. students.forEach(System.out::println);
  21. }
  22. }
  23. class Student {
  24. String name;
  25. int age;
  26. public int getAge () {
  27. return age;
  28. }
  29. public void setAge ( int age) {
  30. this .age = age;
  31. }
  32. public Student (String name, int age) {
  33. this .name = name;
  34. this .age = age;
  35. }
  36. @Override
  37. public String toString () {
  38. return "Student{" +
  39. "name='" + name + '\'' +
  40. ", age=" + age +
  41. '}' ;
  42. }
  43. }

运行结果:

6.Queue接口及其实现类

简单队列用 Queue接口表示,并由LinkedList实现

简单队列队列允许您执行三个基本操作:

  • 从尾部添加元素
  • 从其头部移除元素
  • 在元素顶部审查

Queue接口为三个操作中的每一个定义了两个方法。如果操作不可能,一个方法抛出异常,另一个方法方法返回false或null以指示失败。

方法 描述
boolean add(E e) 如果可能,向队列中添加一个元素。否则,它抛出异常。
boolean offer(E e) 如果不能添加元素,则将元素添加到队列中,而不抛出异常。 它在失败时返回false,在成功时返回true。
E remove() 删除队列的头。如果队列为空,它会抛出异常。此方法返回已移除的项目。
E poll() 从队列中删除元素。如果队列为空而不是抛出异常,则返回null。
Eelement() 偷看队列的头,而不从队列中删除它。 如果队列为空,它会抛出异常。
E peek() 查看队列,如果队列为空而不是抛出异常,则返回null。

代码示例:

 
  1. public static void main (String[] args) {
  2. Queue<String> queue = new LinkedList<>();
  3. queue.offer( "one" );
  4. queue.offer( "two" );
  5. queue.offer( "three" );
  6. queue.offer( "four" );
  7. System.out.println(queue);
  8. //出队
  9. System.out.println( "使用poll()" +queue.poll());
  10. System.out.println(queue);
  11. System.out.println( "使用peek()" +queue.peek());
  12. System.out.println(queue);
  13. }

运行结果:

7.Deque接口及其实现类

双端队列或Deque扩展队列以允许元件从两端插入和移除。
Deque 类的实例表示双端队列。 Deque 接口扩展了 Queue 接口。
它可以用作 FIFO队列 LIFO队列(堆栈)
ArrayDeque和LinkedList类是Deque接口的两个实现类。
ArrayDeque 类由数组支持,而 LinkedList 类由链表支持。
如果您使用Deque作为堆栈,则应该使用 ArrayDeque 作为 Deque 实现。
如果使用 Deque 作为FIFO队列,则应该使用 LinkedList 作为 Deque 实现。

一.ArrayDeque类

常用方法:

用作 LIFO 栈结构
E peek() 检索但不删除栈顶
void push(E e) 将元素压入栈
E pop() 弹出栈顶元素

代码示例:

 
  1. public static void main (String[] args) {
  2. Deque<String> deque= new ArrayDeque();
  3. deque.push( "one" );
  4. deque.push( "two" );
  5. deque.push( "three" );
  6. deque.push( "four" );
  7. System.out.println(deque);
  8. System.out.println( "使用peek():" +deque.peek());
  9. System.out.println(deque);
  10. System.out.println( "使用pop():" +deque.pop());
  11. System.out.println(deque);
  12. }

运行结果:

二.LinkedList类(此处用来实现双端队列)

常用方法:

LinkedList实现双端列表
void addFirst(E e) 在该列表开头插入指定的元素
void addLast(E e) 将指定的元素追加到此列表的末尾
E peekFirst() 检索但不删除此列表的第一个元素,如果此列表为空,则返回 null
E peekLast() 检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null
E pollFirst() 检索并删除此列表的第一个元素,如果此列表为空,则返回 null
E pollLast() 检索并删除此列表的最后一个元素,如果此列表为空,则返回 null

代码示例:

 
  1. public static void main (String[] args) {
  2. Deque<String> deque= new LinkedList<>();
  3. deque.addFirst( "左一" );
  4. deque.addFirst( "左二" );
  5. deque.addFirst( "左三" );
  6. deque.addLast( "右一" );
  7. deque.addLast( "右二" );
  8. deque.addLast( "右三" );
  9. System.out.println(deque);
  10. System.out.println( "peekFirst():" +deque.peekFirst());
  11. System.out.println(deque);
  12. System.out.println( "peekLast():" +deque.peekLast());
  13. System.out.println(deque);
  14. System.out.println( "pollFirst():" +deque.pollFirst());
  15. System.out.println(deque);
  16. System.out.println( "pollLast():" +deque.pollLast());
  17. System.out.println(deque);
  18. }

运行结果:

8.Map接口及其实现类

敲黑板!:Map是Mapping(映射)的简写,不要以为是数据结构中的 Map(图)

Map是一个集合,其中每个元素表示一个键值对作为<key,value> ,<key,value> 对也称为映射中的条目,由Map中的一个内部接口Entry<K,V>表示。键和值必须是引用类型,Map接口虽和Collection没啥关系,但它仍是集合框架中很重要的一部分, 映射不允许任何重复的键。每个键映射到正好一个值。值不必是唯一的。 两个键可以映射到相同的值,Map允许最多一个null作为键,允许多个null作为其值

首先我们了解代表Map集合中每个映射条目的内部接口Map.Entry<K,V>,常用方法如下;

K getKey() 获取该条目中的键
V getValue() 获取该条目中的值
int hashCode() 返回此条目的哈希值
V setValue(V value) 使用指定的值替换该条目中的值

代码示例:(获取条目的唯一方法是使用Map.entrySet() )

 
  1. public static void main (String[] args) {
  2. Map map= new HashMap();
  3. map.put( 1 , "one" );
  4. map.put( 2 , "two" );
  5. map.put( 3 , "three" );
  6. map.put( 4 , "four" );
  7. Set<Map.Entry> entrySet=map.entrySet();
  8. Iterator<Map.Entry> iterator=entrySet.iterator();
  9. while (iterator.hasNext()){
  10. Map.Entry entry1=iterator.next();
  11. System.out.println(entry1.getKey()+ "===" +entry1.getValue());
  12. entry1.setValue( "hello world" );
  13. }
  14. System.out.println(map);
  15. }

运行结果:

由结果可见,entrySet存储的原Map中的视图,从而实现对Map中元素的迭代和修改,Map接口本身是不具备迭代功能的,除了使用entrySet()外,使用keySet()和values()分别获取键,值的视图也是迭代的不错的选择。

Map接口中的常用方法如下:

V put(K key, V value) 向集合中添加映射项目
void putAll(Map<? extends K,? extends V> m) 将指定Map中的值复制到此映射
void clear() 从集合中删除所有的映射
boolean containsKey(Object key) 判断集合中是否包含此键的映射
boolean containsValue(Object value) 判断集合中是否包含此值的映射
Set<K> keySet() 返回由Map中的键组成的集合视图
Collection<V> values() 返回由Map中的值组成的集合视图
Set<Map.Entry<K,V>> entrySet() 返回由Map中的映射条目组成的集合视图

Map常用的实现类:

一.HashMap类

HashMap不保证Map中条目的任何特定的迭代顺序

代码示例:

 
  1. public static void main (String[] args) {
  2. Map map= new HashMap();
  3. map.put( 9 , "one" );
  4. map.put( 2 , "two" );
  5. map.put( 6 , "three" );
  6. map.put( 4 , "four" );
  7. System.out.println(map);
  8. System.out.println( "判断集合中是否包含键为2的映射: " +map.containsKey( 2 ));
  9. System.out.println( "判断集合中国是否包含值为three: " +map.containsValue( "three" ));
  10. Set<Integer> set=map.keySet();
  11. System.out.println(set);
  12. Collection<String> collection=map.values();
  13. System.out.println(collection);
  14. }

运行结果:

二.LinkedHashMap类

LinkedHashMap是Map接口的另一个实现类,继承自HashMap, 它使用双向链表在Map中存储条目,并保持迭代排序作为插入顺序

代码示例:

 
  1. public static void main (String[] args) {
  2. Map map= new LinkedHashMap();
  3. map.put( 9 , "one" );
  4. map.put( 2 , "two" );
  5. map.put( 6 , "three" );
  6. map.put( 4 , "four" );
  7. System.out.println(map);
  8. System.out.println( "判断集合中是否包含键为2的映射: " +map.containsKey( 2 ));
  9. System.out.println( "判断集合中国是否包含值为three: " +map.containsValue( "three" ));
  10. Set<Integer> set=map.keySet();
  11. System.out.println(set);
  12. Collection<String> collection=map.values();
  13. System.out.println(collection);
  14. }

三.TreeMap类

T reeMap是基于一个红黑树的实现 ,具体继承关系如下,它会按照你对Comparable接口或Comparator比较器的实现来对集合中的条目进行排序,同TreeSet相似,如果你设置了Comparator比较器,Comparable接口的功能将会被忽略。

下面的代码使用Comparator比较器对TreeMap中的条目进行排序:

 
  1. public static void main (String[] args) {
  2. //先比较键的长度,再忽略大小比较
  3. Comparator<String> keyComparator = Comparator.comparing(String::length).thenComparing(String::compareToIgnoreCase);
  4. Map map= new TreeMap(keyComparator);
  5. map.put( "one" , 3 );
  6. map.put( "two" , 4 );
  7. map.put( "three" , 2 );
  8. map.put( "four" , 1 );
  9. System.out.println(map);
  10. }

运行结果:

四.HashTable与HashMap的区别

HashTable直接实现Map接口,它与HashMap的区别如下:

  • HashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
  • HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。
  • HashMap允许空键值,而HashTable不允许。

4.Collections集合工具类

详见我的另一博文: https://blog.csdn.net/qq_42013035/article/details/103452711

up-6f5475b026c557b43c156e9b80e4ab53d41.png

up-af7b43587ee778ede3e0af95c7b7268f13e.png

up-251297ccf479925f013ce040c66cc428548.png

up-519049bf6f80724b9ffa165cec89eb3df97.png

up-7c13cc8138e938287d510de1ae008cbb369.png

up-ecf905cde88709ee80eb88e56dd144d1fdd.png

up-be6b40bc8eb50c2d557e1c73a734229d356.png

up-e328ac62d536b276dd8cf9cddf6c8e6e769.png

up-4cb813621dfc6ed56d81477b617510a7133.png

up-7100364db0208985ee61f8c570944c2a374.png

up-7a641e134d95518295bdc77bb6b80379dcd.png

up-45a943f004750b2b7f431d90cea439482e2.png

up-d3011f13a7cec96c5f78a783e84d07ba825.png

up-b2e03b5b70bc8d96b18e7d5d87cf135fb52.png

up-69a75f4ff901c9769e8f4a30fd7956fce5f.png

up-1ba62ef3ee2335672f9afcc7a37d368c8e3.png

up-248b9a564a428640b3c98b1abd546815578.png

up-031fa0666c45111b0036f366250048fc77f.png

up-80c614907ce4773f2e1b81eb4a0c82c2a36.png

up-a2e2145da12334795a2150c1d2ad956e9f5.png

up-c2867dc1c87f7a02973a014de9e681826d4.png

up-c00aac7382ed1a6cd1cbadd80788b2779fe.png

参考:

Java集合框架详解(JDK1.8)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值