1.集合框架

1.1.简述

集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。整个集合框架就围绕一组标准接口而设计。Java 集合框架主要包括两种类型的容器,一种是集合(Collection):存储一个元素集合,另一种是图(Map):存储键/值对(key-value)映射,Collection和Map是Java集合框架的根接口。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。所以Java集合大致可以分为Set、List、Queue和Map四种体系,其中Set代表无序、不可重复的集合,List代表有序、重复的集合,而Map则代表具有映射关系的集合,Java 5 又增加了Queue体系集合,代表一种队列集合实现。Java集合就像一种容器,可以把多个对象(实际上是对象的引用,但习惯上都称对象)“丢进”该容器中。从Java 5 增加了泛型以后,Java集合可以记住容器中对象的数据类型,使得编码更加简洁、健壮。

1.1.1.集合框架体系图

集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:
接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
:是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
集合框架 - 图1

1.1.2.集合架构图

集合框架 - 图2

1.1.3.Collection继承关系

说明:虚线代表接口,实线代表类。

集合框架 - 图3

1.1.4.Map继承关系

说明:虚线代表接口,实线代表类。
集合框架 - 图4

1.2.数组合集合的区别

数组长度在初始化时指定,意味着只能保存定长的数据。而集合可以保存数量不确定的数据。同时可以保存具有映射关系的数据(即关联数组,键值对 key-value)。数组元素即可以是基本类型的值,也可以是对象。集合里只能保存对象(实际上只是保存对象的引用变量),基本数据类型的变量要转换成对应的包装类才能放入集合类中。

2.Collection

2.1.简述

Collection接口是Set、Queue、List的父接口。Collection接口中定义了多种方法可供其子类进行实现,以实现数据操作。

2.2.方法

Modifier and Type Method and Description
boolean add(E e)
确保此集合包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)
将指定集合中的所有元素添加到此集合(可选操作)。
void clear()
从此集合中删除所有元素(可选操作)。
boolean contains(Object o)
如果此集合包含指定的元素,则返回 true 。
boolean containsAll(Collection<?> c)
如果此集合包含指定 集合中的所有元素,则返回true。
boolean equals(Object o)
将指定的对象与此集合进行比较以获得相等性。
int hashCode()
返回此集合的哈希码值。
boolean isEmpty()
如果此集合不包含元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Collection.html) iterator()
返回此集合中的元素的迭代器。
default Stream[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Collection.html) parallelStream()
返回可能并行的 Stream与此集合作为其来源。
boolean remove(Object o)
从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
boolean removeAll(Collection<?> c)
删除指定集合中包含的所有此集合的元素(可选操作)。
default boolean removeIf(Predicate<? super E> filter)
删除满足给定谓词的此集合的所有元素。
boolean retainAll(Collection<?> c)
仅保留此集合中包含在指定集合中的元素(可选操作)。
int size()
返回此集合中的元素数。
default Spliterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Collection.html) spliterator()
创建一个Spliterator在这个集合中的元素。
default Stream[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Collection.html) stream()
返回以此集合作为源的顺序 Stream 。
Object[] toArray()
返回一个包含此集合中所有元素的数组。
T[] toArray(T[] a)
返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

2.3.使用Iterator遍历集合元素

Iterator接口也是java集合框架的成员,但是与collection系列、map系列不一样,collection系列和map系列主要是用来盛装其他对象,而iterator接口主要用于遍历collection集合中的元素,所以iterator又称为迭代器。

  1. List<String> list =Arrays.asList("java","js","vue");
  2. Iterator<String> iterator = list.iterator();
  3. while(iterator.hasNext()){
  4. //集合元素的值传给了迭代变量,仅仅传递了对象引用。保存的仅仅是指向对象内存空间的地址
  5. String next = iterator.next();
  6. next ="测试";
  7. System.out.println(next);
  8. }
  9. System.out.println(list);
  10. //运行结果
  11. 测试
  12. 测试
  13. 测试
  14. [java,js,vue]

当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量(就如同参数传递是值传递,基本数据类型传递的是值,引用类型传递的仅仅是对象的引用变量),所以修改迭代变量的值对集合元素本身没有任何影响。

2.4.使用Lambda表达式遍历集合

iterable接口是collection接口的父接口,iterable接口的forEach(Consumer action)方法所需的参数类型是一个函数式接口,当程序使用iterable的forEach遍历集合元素时,程序会依次将集合元素传给Consumer的accept(T t)抽象方法。

  1. List<String> list =Arrays.asList("java","js","vue");
  2. list.forEach(obj -> System.out.println("集合元素:"+obj));
  3. //运行结果
  4. 集合元素:java
  5. 集合元素:js
  6. 集合元素:vue

2.5.使用Lambda表达式遍历Iterator

Iterator接口的forEachRemaining(Consumer action)方法所需的参数类型是一个函数式接口,传给该方法的参数是一个Lambda表达式,当程序使用Iterator的forEachRemaining遍历集合元素时,程序会依次将集合元素传给Consumer的accept(T t)抽象方法。

  1. List<String> list =Arrays.asList("java","js","vue");
  2. Iterator<String> iterator = list.iterator();
  3. iterator.forEachRemaining(obj -> System.out.println("集合元素"+obj));
  4. //运行结果
  5. 集合元素:java
  6. 集合元素:js
  7. 集合元素:vue

2.6.使用foreach循环遍历集合元素

  1. List<String> list =Arrays.asList("java","js","vue");
  2. for(String obj : list){
  3. System.out.println("集合元素"+obj)
  4. }
  5. //运行结果
  6. 集合元素:java
  7. 集合元素:js
  8. 集合元素:vue

3.Set

3.1.简述

Set集合与Collection集合基本相同,没有提供任何额外的方法。实际上Set就是Collection,只是行为略有不同(Set不允许包含重复元素)。Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入,并且最多一个空元素。

HashSet:底层数据结构是哈希表。(无序,唯一)
LinkedHashSet:底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
TreeSet:底层数据结构是红黑树。(唯一,有序)。

3.2.方法

Modifier and Type Method and Description
boolean add(E e)
如果指定的元素不存在,则将其指定的元素添加(可选操作)。
boolean addAll(Collection<? extends E> c)
将指定集合中的所有元素添加到此集合(如果尚未存在)(可选操作)。
void clear()
从此集合中删除所有元素(可选操作)。
boolean contains(Object o)
如果此集合包含指定的元素,则返回 true 。
boolean containsAll(Collection<?> c)
返回 true如果此集合包含所有指定集合的元素。
boolean equals(Object o)
将指定的对象与此集合进行比较以实现相等。
int hashCode()
返回此集合的哈希码值。
boolean isEmpty()
如果此集合不包含元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Set.html) iterator()
返回此集合中元素的迭代器。
boolean remove(Object o)
如果存在,则从该集合中删除指定的元素(可选操作)。
boolean removeAll(Collection<?> c)
从此集合中删除指定集合中包含的所有元素(可选操作)。
boolean retainAll(Collection<?> c)
仅保留该集合中包含在指定集合中的元素(可选操作)。
int size()
返回此集合中的元素数(其基数)。
default Spliterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Set.html) spliterator()
在此集合中的元素上创建一个 Spliterator 。
Object[] toArray()
返回一个包含此集合中所有元素的数组。
T[] toArray(T[] a)
返回一个包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

3.3.HashSet

3.3.1.简述

HashSet的实质是一个HashMap,HashSet的所有集合元素,构成了HashMap的key,其value为一个静态Object对象。因此HashSet的所有性质,HashMap的key所构成的集合都具备。HashSet是Set接口的典型实现,实现了Set接口中的所有方法,并没有添加额外的方法,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素。因此具有很好的存取和查找性能。当想HashSet集合存入一个元素时,HashSet会调用hashCode()方法来获取元素对象的hashCode值,然后决定该对象在hashSet中的存储位置,如果有两个元素通过equals()方法比较相等,但是它们的hashCode值不一样,HashSet就会把它们存储在不同的位置。HashSet判断两个元素相等的标准:两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等

3.3.2.特点

(1)不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
(2)HashSet不是同步的,如果多个线程同时访问一个HashSet,则必须通过代码来保证其同步。
(3)集合元素值可以是null。
除此之外,HashSet判断两个元素是否相等的标准也是其一大特点。HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

3.3.2.1.equals方法

equals() 的作用是用来判断两个对象是否相等
equals() 定义在JDK的Object.java中。通过判断两个对象的地址是否相等(即,是否是同一个对象)来区分它们是否相等。源码如下:

  1. public boolean equals(Object obj) {
  2. return (this == obj);
  3. }

3.3.2.2.hashCode方法

hashCode() 的作用是获取哈希码,也称为散列码,它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置
hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。虽然,每个Java类都包含hashCode() 函数。但是,仅仅当创建某个类的散列表时,该类的hashCode() 才有用,其它情况下类的hashCode() 没有作用。
在散列表中,在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
hashCode()也分两种情况。一种是Object类中默认的方法,另一种是在子类中重写的方法。
(1)没有覆盖hashCode()方法
当它的通过hashCode()比较两个对象时,实际上是比较两个对象是不是同一个对象。这时,等价于通过“==”去比较这两个对象,即两个对象的内存地址是否相同。
(2)覆盖类的hashCode()方法
覆盖类的hashCode()方法来让hashCode()通过其它方式比较两个对象是否相等。通常的做法是:若两个对象的内容相等,则hashCode()方法返回true,否则,返回fasle。

3.3.2.3.散列

散列使用一个散列函数,将一个键映射到一个索引上。映射表(map)又称字典(dictionary)、散列表(hash table)或者关联数组(associate array),是一种使用散列实现的数据结构,用来存取条目的容器对象。
Java合集框架定义了java.util.Map接口来对映射表建模,三个具体实现类为java.util.HashMap(散列实现)、java.util.LinkedHashMap(使用LinkedList)、java.util.TreeMap(使用红黑树)。
存储了值的数组称为散列表(hash table),将键映射到散列表中的索引上的函数称为散列函数(hash function)。散列(hashing)是一种无需进行搜素,即可通过从键得到的索引来获取值的技术

3.3.3.LinkedHashSet类

LinkedHashSet是HashSet对的子类,也是根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,使得元素是以插入的顺序来保存的。当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。但是由于要维护元素的插入顺序,在性能上略低与HashSet,但在迭代访问Set里的全部元素时有很好的性能。LinkedHashSet依然不允许元素重复,判断重复标准与HashSet一致

3.4.TreeSet

3.4.1.简述

TreeSet是SortedSet接口的实现类,正如SortedSet名字所暗示的,TreeSet可以确保集合元素处于排序状态。对于TreeSet集合而言,判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj)方法比较是否返回0,如果通过compareTo(Object obj)方法比较返回0,TreeSet则会认为它们相等,不予添加入集合内,否则就认为它们不相等,添加到集合内。如果向TreeSet中添加了一个可变对象后,并且后面程序修改了该可变对象的实例变量,这将导致它与其他对象的大小顺序发生了改变,但TreeSet不会再次调整它们。
TreeSet是根据红黑树结构找到集合元素的存储位置。

3.4.2.方法

Modifier and Type Method and Description
boolean add(E e)
将指定的元素添加到此集合(如果尚未存在)。
boolean addAll(Collection<? extends E> c)
将指定集合中的所有元素添加到此集合中。
E ceiling(E e)
返回此集合中最小元素大于或等于给定元素,如果没有此元素,则返回 null 。
void clear()
从此集合中删除所有元素。
Object clone()
返回此 TreeSet实例的浅拷贝。
Comparator<? super E> comparator()
返回用于对该集合中的元素进行排序的比较器,或null,如果此集合使用其元素的natural ordering
boolean contains(Object o)
如果此集合包含指定的元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) descendingIterator()
以降序返回该集合中的元素的迭代器。
NavigableSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) descendingSet()
返回此集合中包含的元素的反向排序视图。
E first()
返回此集合中当前的第一个(最低)元素。
E floor(E e)
返回此集合中最大的元素小于或等于给定元素,如果没有这样的元素,则返回 null 。
SortedSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) headSet(E toElement)
返回此集合的部分的视图,其元素严格小于 toElement 。
NavigableSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) headSet(E
toElement, boolean inclusive)
返回该集合的部分的视图,其元素小于(或等于,如果 inclusive为真) toElement 。
E higher(E e)
返回严格大于给定元素的该集合中的最小元素,如果没有此元素则返回 null 。
boolean isEmpty()
如果此集合不包含元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) iterator()
以升序返回该集合中的元素的迭代器。
E last()
返回此集合中当前的最后(最高)元素。
E lower(E e)
返回这个集合中最大的元素严格小于给定的元素,如果没有这样的元素,则返回 null 。
E pollFirst()
检索并删除第一个(最低)元素,或返回 null如果该集合为空。
E pollLast()
检索并删除最后一个(最高)元素,如果此集合为空,则返回 null 。
boolean remove(Object o)
如果存在,则从该集合中删除指定的元素。
int size()
返回此集合中的元素数(其基数)。
Spliterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) spliterator()
在此集合中的元素上创建late-binding故障切换 Spliterator
NavigableSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) subSet(E fromElement, boolean fromInclusive, E
toElement, boolean toInclusive)
返回该集合的部分的视图,其元素的范围从 fromElement到 toElement 。
SortedSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) subSet(E fromElement, E toElement)
返回此集合的部分的视图,其元素的范围从 fromElement (含)到 toElement ,排他。
SortedSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) tailSet(E fromElement)
返回此组件的元素大于或等于 fromElement的部分的视图。
NavigableSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/TreeSet.html) tailSet(E fromElement, boolean inclusive)
返回此集合的部分的视图,其元素大于(或等于,如果 inclusive为真) fromElement 。

3.4.3.排序方式

TreeSet并不是通过元素的插入顺序进行排序的,而是通过集合中元素属性进行排序方式来实现的。TreeSet支持两种排序方法:自然排序和定制排序。在默认情况下,TreeSet采用自然排序。

3.4.3.1.自然排序

TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列,这种方式就是自然排序。

  1. o1.compareTo(o2)
  2. 如果该方法返回=0,则表明两个对象相等;
  3. 如果该方法返回>0,则表明o1大于o2
  4. 如果该方法返回<0,则表明o1小于o2

Java的一些常用类已经实现了Comparable接口,并提供了比较大小的标准。例如,String按字符串的UNICODE值进行比较,Integer等所有数值类型对应的包装类按它们的数值大小进行比较。除了这些已经实现Comparable接口类之外,如果试图把一个对象添加到TreeSet时,则该对象的类必须实现Comparable接口,否则就会出现异常。TreeSet中只能添加同一种类型的对象,否则无法比较,会出现异常。

3.4.3.2.定制排序

在创建TreeSet对象是,提供Comparator对象与TreeSet集合关联,由Comparator对象负责元素的排序逻辑,从而实现自定义排序。

  1. int compare(T o1,T o2)//用于比较o1和o2的大小
  2. 如果该方法返回=0,则表明两个对象相等;
  3. 如果该方法返回>0,则表明o1大于o1
  4. 如果该方法返回<0,则表明o1小于o1

举例说明:

  1. User u1 = new User();
  2. u1.setAge(20);
  3. User p2 =new User();
  4. u2.setAge(30);
  5. Comparator<User> comparator = new Comparator<User>() {
  6. @Override
  7. public int compare(User o1, User o2) {
  8. //年龄越小的排在越后面
  9. if(o1.getAge() < o2.getAge()){
  10. return 1;
  11. }else if(o1.getAge() > o2.getAge()){
  12. return -1;
  13. }else{
  14. return 0;
  15. }
  16. }
  17. };
  18. TreeSet<User> set = new TreeSet<User>(comparator);
  19. set.add(p1);
  20. set.add(p2);
  21. System.out.println(set);

3.5.EnumSet

3.5.1.简述

EnumSet是一个专为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显示或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在EnumSet类内的定义顺序来决定集合元素的顺序。(比较少用)

  1. public enum Seasons {
  2. AUTMN,
  3. WINTER,
  4. SPRING,
  5. SUMMER
  6. }
  7. public static void main(String[] args) {
  8. EnumSet<Seasons> coldSeasons = EnumSet.of(Seasons.AUTMN, Seasons.WINTER);
  9. for (Seasons seasons : coldSeasons) {
  10. System.out.println("SEASON:"+seasons.name());
  11. }
  12. }
  13. //运行结果
  14. SEASON:AUTUMN
  15. SEASON:WINTER

3.5.2.特点

(1)EnumSet集合不允许加入null元素。EnumSet中的所有元素都必须是指定枚举类型的枚举值。
(2)EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的类方法来创建EnumSet对象。

3.5.3.方法

EnumSet没有其他额外增加的方法,只是增加了一些创建EnumSet对象的方法。

Modifier and Type Method and Description
static > EnumSet allOf(Class elementType)
创建一个包含指定元素类型中所有元素的枚举集。
EnumSet[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/EnumSet.html) clone()
返回此集合的副本。
static >EnumSet complementOf(EnumSet s)
创建与指定枚举集具有相同元素类型的枚举集,最初包含此类型的所有元素,该元素 包含在指定的集合中。
static >EnumSet copyOf(Collection c)
创建从指定集合初始化的枚举集。
static >EnumSet copyOf(EnumSet s)
创建与指定的枚举集相同的元素类型的枚举集,最初包含相同的元素(如果有)。
static >EnumSet noneOf(Class elementType)
使用指定的元素类型创建一个空的枚举集。
static >EnumSet of(E e)
创建一个最初包含指定元素的枚举集。
static >EnumSet of(E first, E… rest)
创建一个最初包含指定元素的枚举集。
static >EnumSet of(E e1, E e2)
创建一个最初包含指定元素的枚举集。
static >EnumSet of(E e1, E e2, E e3)
创建一个最初包含指定元素的枚举集。
static >EnumSet of(E e1, E e2, E e3, E e4)
创建一个最初包含指定元素的枚举集。
static >EnumSet of(E e1, E e2, E e3, E e4, E e5)
创建一个最初包含指定元素的枚举集。
static >EnumSet range(E from, E to)
创建最初包含由两个指定端点定义的范围内的所有元素的枚举集。

3.6.Set集合使用

3.6.1.排序

3.6.1.1.传统排序

  1. Set<String> set = new HashSet<>();
  2. Set<String> sortSet = new TreeSet<String>(new Comparator<String>{
  3. @Override
  4. public int compare(String o1,String o2){
  5. return o1.compareTo(o2);//正序排序
  6. }
  7. });
  8. sortSet.addAll(set);

3.6.1.2.lambda表达式

  1. Set<String> sortSet = new TreeSet<>(((o1,o2) -> { return o1.compareTo(o2);//正序排序 }))
  2. sortSet.addAll(set);

3.6.1.3.Comparator

在jdk1.8以后,Comparator有正序排序(Comparator.naturalOrder())和反序排序(Comparator.reverseOrder())。

  1. TreeSet<String> sortSet = new TreeSet<>(Comparator.naturalOrder());
  2. sortSet.addAll(set);

3.6.1.4.Stream

使用Stream还可以转还成Set或者List,转换成Set需要创建TreeSet,而List可以直接转换,而且List是有序。

  1. List list = new HashSet<String>().stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
  2. Set<String> tmp = set.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toSet());
  3. TreeSet<String> sortSet = new TreeSet<>();
  4. sortSet.addAll(tmp);

4.List

4.1.简述

List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素 。List集合默认按元素的添加顺序设置元素的索引,例如第一个添加的元素索引为0,第二个添加的元素索引为1,……,第N个添加的元素索引为N。
List作为Collection接口的子接口,可以使用Collection接口里的全部方法,而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法。注意的是List判断两个对象相等只要通过equals()方法比较返回true。

ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高

4.2.方法

Modifier and Type Method and Description
boolean add(E e)
将指定的元素追加到此列表的末尾(可选操作)。
void add(int index, E element)
将指定的元素插入此列表中的指定位置(可选操作)。
boolean addAll(Collection<? extends E> c)
按指定集合的迭代器(可选操作)返回的顺序将指定集合中的所有元素附加到此列表的末尾。
boolean addAll(int index, Collection<? extends E> c)
将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。
void clear()
从此列表中删除所有元素(可选操作)。
boolean contains(Object o)
如果此列表包含指定的元素,则返回 true 。
boolean containsAll(Collection<?> c)
如果此列表包含指定 集合的所有元素,则返回true。
boolean equals(Object o)
将指定的对象与此列表进行比较以获得相等性。
E get(int index)
返回此列表中指定位置的元素。
int hashCode()
返回此列表的哈希码值。
int indexOf(Object o)
返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
boolean isEmpty()
如果此列表不包含元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/List.html) iterator()
以正确的顺序返回该列表中的元素的迭代器。
int lastIndexOf(Object o)
返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
ListIterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/List.html) listIterator()
返回列表中的列表迭代器(按适当的顺序)。
ListIterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/List.html) listIterator(int index)
从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
E remove(int index)
删除该列表中指定位置的元素(可选操作)。
boolean remove(Object o)
从列表中删除指定元素的第一个出现(如果存在)(可选操作)。
boolean removeAll(Collection<?> c)
从此列表中删除包含在指定集合中的所有元素(可选操作)。
default void replaceAll(UnaryOperator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/List.html) operator)
将该列表的每个元素替换为将该运算符应用于该元素的结果。
boolean retainAll(Collection<?> c)
仅保留此列表中包含在指定集合中的元素(可选操作)。
E set(int index, E element)
用指定的元素(可选操作)替换此列表中指定位置的元素。
int size()
返回此列表中的元素数。
default void sort(Comparator<? super E> c)
使用随附的 Comparator排序此列表来比较元素。
default Spliterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/List.html) spliterator()
在此列表中的元素上创建一个Spliterator
List[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/List.html) subList
(int fromIndex, int toIndex)
返回此列表中指定的 fromIndex (含)和 toIndex之间的视图。
Object[] toArray()
以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
T[] toArray(T[] a)
以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。

4.3.ArrayList

4.3.1简述

ArrayList作为List类的典型实现,完全支持之前介绍的List接口的全部功能。ArrayList类基于数组实现的List类,所以ArrayList类封装了一个动态的、允许再分配的Object[]数组,因为ArrayList用法类似于数组,且其容量可按需要动态调整,亦被称为动态数组。ArrayList对象使用initalCapacity参数来设置该数组的长度,当向ArrayList中添加元素超过了该数组的长度时,它们的initalCapacity会自动增加。
image.png

4.3.2.方法

Modifier and Type Method and Description
boolean add(E e)
将指定的元素追加到此列表的末尾。
void add(int index, E element)
在此列表中的指定位置插入指定的元素。
boolean addAll(Collection<? extends E> c)
按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。
boolean addAll(int index, Collection<? extends E> c)
将指定集合中的所有元素插入到此列表中,从指定的位置开始。
void clear()
从列表中删除所有元素。
Object clone()
返回此 ArrayList实例的浅拷贝。
boolean contains(Object o)
如果此列表包含指定的元素,则返回 true 。
void ensureCapacity(int minCapacity)
如果需要,增加此 ArrayList实例的容量,以确保它可以至少保存最小容量参数指定的元素数。
void forEach(Consumer<? super E> action)
对 Iterable的每个元素执行给定的操作,直到所有元素都被处理或动作引发异常。
E get(int index)
返回此列表中指定位置的元素。
int indexOf(Object o)
返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
boolean isEmpty()
如果此列表不包含元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ArrayList.html) iterator()
以正确的顺序返回该列表中的元素的迭代器。
int lastIndexOf(Object o)
返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
ListIterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ArrayList.html) listIterator()
返回列表中的列表迭代器(按适当的顺序)。
ListIterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ArrayList.html) listIterator(int index)
从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
E remove(int index)
删除该列表中指定位置的元素。
boolean remove(Object o)
从列表中删除指定元素的第一个出现(如果存在)。
boolean removeAll(Collection<?> c)
从此列表中删除指定集合中包含的所有元素。
boolean removeIf(Predicate<? super E> filter)
删除满足给定谓词的此集合的所有元素。
protected void removeRange(int fromIndex, int toIndex)
从这个列表中删除所有索引在 fromIndex (含)和 toIndex之间的元素。
void replaceAll(UnaryOperator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ArrayList.html) operator)
将该列表的每个元素替换为将该运算符应用于该元素的结果。
boolean retainAll(Collection<?> c)
仅保留此列表中包含在指定集合中的元素。
E set(int index, E element)
用指定的元素替换此列表中指定位置的元素。
int size()
返回此列表中的元素数。
void sort(Comparator<? super E> c)
使用提供的 Comparator对此列表进行排序以比较元素。
Spliterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ArrayList.html) spliterator()
在此列表中的元素上创建late-binding故障快速 Spliterator
List[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ArrayList.html) subList(int fromIndex, int toIndex)
返回此列表中指定的 fromIndex (包括)和 toIndex之间的独占视图。
Object[] toArray()
以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
T[] toArray(T[] a)
以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。
void trimToSize()
修改这个 ArrayList实例的容量是列表的当前大小。

4.3.3.使用迭代器遍历集合

  1. List<String> list = new ArrayList<String>();
  2. list.add("Hello");
  3. list.add("world");
  4. list.add("!");
  5. Iterator<String> iterator = list.iterator();
  6. while(iterator.hasNext()){
  7. String next = iterator.next();
  8. System.out.println(next);
  9. }
  10. //运行结果
  11. Hello
  12. world
  13. !

4.3.4.通过索引值去遍历

遍历ArrayList时,使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低。

  1. for(int i=0;i<list.size();i++){
  2. System.out.println(list.get(i));
  3. }
  4. //运行结果
  5. Hello
  6. world
  7. !

4.3.5.for循环遍历

  1. for(String obj : list){
  2. System.out.println(obj);
  3. }
  4. //运行结果
  5. Hello
  6. world
  7. !

4.4.Vector

和ArrayList用法一致,Vector是一个比较老的类,在JDK 1.0即已出现,不推荐使用。虽然Vector是线程安全的,但是在线程安全方面也不推荐使用。推荐方案如下:

  1. List<String> synList = Collections.synchronizedList(lst);

4.5.LinkedList

4.5.1.简述

LinkedList类是List接口的实现类——这意味着它是一个List集合,可以根据索引来随机访问集合中的元素。除此之外,LinkedList还实现了Deque接口,可以被当作成双端队列来使用,因此既可以被当成“栈”来使用,也可以当成队列来使用。LinkedList的实现机制与ArrayList完全不同。ArrayList内部是以数组的形式来保存集合中的元素的,因此随机访问集合元素时有较好的性能,LinkedList底层通过链表来实现,随着元素的增加不断向链表的后端增加节点。LinkedList是一个双向链表,每一个节点都拥有指向前后节点的引用。相比于ArrayList来说,LinkedList的随机访问效率更低,但在插入、删除元素时性能比较出色。LinkedList本质上来讲就是调用默认构造函数,创建一个链表。由于维护了一个表头表尾为Node对象的变量。可以进行后续的添加元素到链表中的操作,以及其他删除,插入等操作。也因此实现了双向队列的功能,即可向表头加入元素,也可以向表尾加入元素。
image.png

4.5.2.方法

Modifier and Type Method and Description
boolean add(E e)
将指定的元素追加到此列表的末尾。
void add(int index, E element)
在此列表中的指定位置插入指定的元素。
boolean addAll(Collection<? extends E> c)
按照指定集合的迭代器返回的顺序将指定集合中的所有元素追加到此列表的末尾。
boolean addAll(int index, Collection<? extends E> c)
将指定集合中的所有元素插入到此列表中,从指定的位置开始。
void addFirst(E e)
在该列表开头插入指定的元素。
void addLast(E e)
将指定的元素追加到此列表的末尾。
void clear()
从列表中删除所有元素。
Object clone()
返回此 LinkedList的浅版本。
boolean contains(Object o)
如果此列表包含指定的元素,则返回 true 。
Iterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) descendingIterator()
以相反的顺序返回此deque中的元素的迭代器。
E element()
检索但不删除此列表的头(第一个元素)。
E get(int index)
返回此列表中指定位置的元素。
E getFirst()
返回此列表中的第一个元素。
E getLast()
返回此列表中的最后一个元素。
int indexOf(Object o)
返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int lastIndexOf(Object o)
返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
ListIterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) listIterator(int index)
从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。
boolean offer(E e)
将指定的元素添加为此列表的尾部(最后一个元素)。
boolean offerFirst(E e)
在此列表的前面插入指定的元素。
boolean offerLast(E e)
在该列表的末尾插入指定的元素。
E peek()
检索但不删除此列表的头(第一个元素)。
E peekFirst()
检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。
E peekLast()
检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null 。
E poll()
检索并删除此列表的头(第一个元素)。
E pollFirst()
检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。
E pollLast()
检索并删除此列表的最后一个元素,如果此列表为空,则返回 null 。
E pop()
从此列表表示的堆栈中弹出一个元素。
void push(E e)
将元素推送到由此列表表示的堆栈上。
E remove()
检索并删除此列表的头(第一个元素)。
E remove(int index)
删除该列表中指定位置的元素。
boolean remove(Object o)
从列表中删除指定元素的第一个出现(如果存在)。
E removeFirst()
从此列表中删除并返回第一个元素。
boolean removeFirstOccurrence(Object o)
删除此列表中指定元素的第一个出现(从头到尾遍历列表时)。
E removeLast()
从此列表中删除并返回最后一个元素。
boolean removeLastOccurrence(Object o)
删除此列表中指定元素的最后一次出现(从头到尾遍历列表时)。
E set(int index, E element)
用指定的元素替换此列表中指定位置的元素。
int size()
返回此列表中的元素数。
Spliterator[E](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) spliterator()
在此列表中的元素上创建late-binding故障快速 Spliterator
Object[] toArray()
以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
T[] toArray(T[] a)
以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。

4.5.3.通过迭代器遍历

  1. List<String> linkedList = new LinkedList<String>();
  2. linkedList.add("my");
  3. linkedList.add("name");
  4. linkedList.add("is");
  5. linkedList.add("maxteng");
  6. Iterator<String> iterator = linkedList.iterator();
  7. while(iterator.hasNext()){
  8. String next = iterator.next();
  9. System.out.println(next);
  10. }
  11. //运行结果
  12. my
  13. name
  14. is
  15. maxteng


4.5.4通过快速随机访问遍历

  1. for(int i=0;i<linkedList.size();i++){
  2. System.out.println(linkedList.get(i));
  3. }
  4. //运行结果
  5. my
  6. name
  7. is
  8. maxteng


4.5.5.通过for循环遍历

  1. for(String obj : linkedList){
  2. System.out.println(obj);
  3. }
  4. //运行结果
  5. my
  6. name
  7. is
  8. maxteng


4.5.6.通过pollFirst()遍历

  1. while(linkedList.pollFirst() != null) {
  2. System.out.println(linkedList);
  3. }
  4. //运行结果
  5. [name, is, maxteng]
  6. [is, maxteng]
  7. [maxteng]
  8. []


4.5.7.通过pollLast()遍历

  1. while(linkedList.pollLast() != null) {
  2. System.out.println(linkedList);
  3. }
  4. //运行结果
  5. [my, name, is]
  6. [my, name]
  7. [my]
  8. []


4.5.8通过removeFirst()遍历

  1. try {
  2. while(linkedList.removeFirst() != null) {
  3. System.out.println(linkedList);
  4. }
  5. } catch (NoSuchElementException e) {
  6. }
  7. //运行结果
  8. [name, is, maxteng]
  9. [is, maxteng]
  10. [maxteng]
  11. []


4.5.9.通过removeLast()遍历

  1. try {
  2. while(linkedList.removeLast() != null) {
  3. System.out.println(linkedList);
  4. }
  5. } catch (NoSuchElementException e) {
  6. }
  7. //运行结果
  8. [my, name, is]
  9. [my, name]
  10. [my]
  11. []

4.6.使用场景

涉及到“动态数组”、“栈”、“队列”、“链表”等结构应该使用List。
可以根据下面的标准来选择哪个List。
(1)LinkedList:场景需要快速插入、删除元素。
(2)ArrayList:场景需要快速随机访问元素。
(3)非同步类:“单线程环境” 或者 “多线程环境,但List仅仅只会被单个线程操作”。
(4)同步的类:“多线程环境,且List可能同时被多个线程操作”。

4.7.List集合使用

4.7.1.分组

4.7.1.1.Java 8特性

其中commonRemark是实体类GarGarmentMaterial的属性

  1. Map<String,List<GarGarmentMaterial>> map = list.stream().collect(Collectors.groupingBy(GarGarmentMaterial::getCommonRemark));

4.7.1.2.自定义

其中commonRemark是实体类GarGarmentMaterial的属性

  1. public Map<String,List<GarGarmentMaterial>> listGroupBy(List<GarGarmentMaterial> list){
  2. Map<String,List<Entity>> map = new HashMap<>();
  3. for(GarGarmentMaterialtmp:list){
  4. List<GarGarmentMaterial> tmpList = map.get(tmp.getCommonRemark());
  5. if(null == tmpList){
  6. tmpList = new ArrayList<>();
  7. tmpList.add(tmp);
  8. map.put(tmp.getCommonRemark(),tmpList);
  9. }else{
  10. tmpList.add(tmp);
  11. }
  12. }
  13. return map;
  14. }

5.Queue

5.1.简述

Queue用于模拟队列这种数据结构。队列通常是指“先进先出(FIFO)”的容器。队列的头部保存在队列中存放时间最长的元素,尾部保存存放时间最短的元素。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素。通常,队列不允许随机访问队列中的元素。
集合框架 - 图7
Queue(队列)接口继承自Collection,用来表示内部元素具有先后顺序的集合。除了基本的集合操作外,队列还提供了其他插入、删除和检查操作。

5.2.方法

Modifier and Type Method and Description
boolean add(E e)
将指定的元素插入到此队列中,如果可以立即执行此操作,而不会违反容量限制, true在成功后返回 IllegalStateException如果当前没有可用空间,则抛出IllegalStateException。
E element()
检索,但不删除,这个队列的头。
boolean offer(E e)
如果在不违反容量限制的情况下立即执行,则将指定的元素插入到此队列中。
E peek()
检索但不删除此队列的头,如果此队列为空,则返回 null 。
E poll()
检索并删除此队列的头,如果此队列为空,则返回 null
E remove()
检索并删除此队列的头。

add和offer都是在尾部添加元素,并且不建议添加null元素,否则会报空指针,但是不同的是 add方法在添加失败(比如说队列已满)时会报一些运行时的错误,而 offer方法即使在添加失败时也不会奔溃,只会返回 false。remove和poll都是删除并返回头部,不同的是当队列为空时remove方法会报 NoSuchElementException 异常,而poll不会奔溃,只会返回 null。element和peek都是获取但不删除,不同的是当队列为空时 element会抛出异常,而peek不会奔溃,只会返回 null。

5.3.PriorityQueue

5.3.1.简述

PriorityQueue保存队列元素的顺序不是按加入队列的顺序,而是按队列元素的大小进行重新排序。因此当调用peek或pool方法取出队列中头部的元素时,并不是取出最先进入队列的元素,而是取出队列中的最小的元素。PriorityQueue本质也是一个动态数组,在这一方面与ArrayList是一致的。

5.3.2.排序

PriorityQueue中的元素默认是自然排序,也就是如果元素是数字,那么默认排序是从小到大,如果元素是字符串则默认排序按字典序排列,当然也可以通过提供的比较器Comparator在队列实例化时指定的排序方式。

  1. //默认排序
  2. PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
  3. priorityQueue.add(5);
  4. priorityQueue.add(3);
  5. priorityQueue.add(7);
  6. priorityQueue.add(2);
  7. priorityQueue.add(9);
  8. while (!priorityQueue.isEmpty()){
  9. System.out.print(priorityQueue.poll() + "=>");
  10. }
  11. //自定义排序由大道小
  12. Comparator<Integer> cmp = new Comparator<Integer>() {
  13. public int compare(Integer e1, Integer e2) {
  14. return e2 - e1;
  15. }
  16. };
  17. while (!priorityQueue.isEmpty()){
  18. System.out.print(priorityQueue.poll() + "=>");
  19. }
  20. //运行结果
  21. 2=>3=>5=>7=>9
  22. 9=>7=>5=>3=>2

5.3.3.特性

(1)队列元素不是根据加入时间进行排序,是根据元素大小进行排序。
(2)默认容量为11。
(3)自动扩容。如果容量小于64,两倍增长扩容,否则增长50%。
(4)无边界容器。
(5)不支持加入null元素。
(6)非线程安全。
(7)支持被序列化。
(8)入队出队的时间复杂度O(log(n))。

6.Map

6.1.简述

最常用的集合类型之一。Map是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键对象和一个值对象。其中键(key)对象不允许重复,而值(value)对象可以重复,并且值对象还可以是Map类型的(如:Map<String,Map<String,String>),就像数组中的元素还可以是数组一样。Map 接口主要有两个实现类:HashMap 类和 TreeMap 类。其中HashMap 类按哈希算法来存取键对象,而 TreeMap 类可以对键对象进行排序。Map与List、Set集合的某些特性有重合。
集合框架 - 图8

6.2.方法

Modifier and Type Method and Description
void clear()
从该集合中删除所有的映射(可选操作)。
default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
尝试计算指定键的映射及其当前映射的值(如果没有当前映射, null )。
default V computeIfAbsent(K key, Function<? super K,?extends V> mappingFunction)
如果指定的键尚未与值相关联(或映射到 null ),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非 null 。
default V computeIfPresent(K key, BiFunction<? super K,?super V,? extends V> remappingFunction)
如果指定的密钥的值存在且非空,则尝试计算给定密钥及其当前映射值的新映射。
boolean containsKey(Object key)
如果此映射包含指定键的映射,则返回 true 。
boolean containsValue(Object value)
如果此集合将一个或多个键映射到指定的值,则返回 true 。
Set[Map.Entry](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Map.Entry.html)<[K](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Map.html),[V](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Map.html)> entrySet()
返回此集合中包含的映射的Set集合。
boolean equals(Object o)
将指定的对象与此映射进行比较以获得相等性。
default void forEach(BiConsumer<? super K,? super V> action)
对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。
V get(Object key)
返回到指定键所映射的值,或 null如果此映射包含该键的映射。
default V getOrDefault(Object key, V defaultValue)
返回到指定键所映射的值,或 defaultValue如果此映射包含该键的映射。
int hashCode()
返回此地图的哈希码值。
boolean isEmpty()
如果此地图不包含键值映射,则返回 true 。
Set[K](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Map.html) keySet()
返回此地图中包含的键的Set视图。
default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。
V put(K key, V value)
将指定的值与该映射中的指定键相关联(可选操作)。
void putAll(Map<? extends K,? extends V> m)
将指定集合的所有映射复制到此映射(可选操作)。
default V putIfAbsent(K key, V value)
如果指定的键尚未与某个值相关联(或映射到 null )将其与给定值相关联并返回 null ,否则返回当前值。
V remove(Object key)
如果存在(从可选的操作),从该集合中删除一个键的映射。
default boolean remove(Object key, Object value)
仅当指定的密钥当前映射到指定的值时删除该条目。
default V replace(K key, V value)
只有当目标映射到某个值时,才能替换指定键的条目。
default boolean replace(K key, V oldValue, V newValue)
仅当当前映射到指定的值时,才能替换指定键的条目。
default void replaceAll(BiFunction<? super K,? super V,? extends V> function)
将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。
int size()
返回此地图中键值映射的数量。
Collection[V](https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Map.html) values()
返回此集合中包含的值的Collection集合。

6.3.遍历

  1. // Map.Entry遍历
  2. Map<String,List<String>> map = new HashMap<>();
  3. for(Map.Entry<String, List<String>> tmp : map.entrySet()){
  4. String label = tmp.getKey();
  5. List<String> values = tmp.getValue()
  6. }
  7. //keySet遍历,分别获取key和value
  8. Set<String> keys = map.keySet();
  9. Iterator<String> it = ks.iterator();
  10. while (it.hasNext()) {
  11. String key = it.next();
  12. List<String> value = map.get(key);
  13. }
  14. //通过value遍历,不能获取key
  15. Collection<List<String>> list = map.values();
  16. Iterator<List<String>> it = list.iterator();
  17. while (it.hasNext()) {
  18. List<String> value = it.next();
  19. }

6.4.HashMap

6.4.1.简述

HashMap是我们最常用的Map,实现了Map接口,继承了AbstractMap类,它根据key的HashCode值来存储数据,通过key可以获取它对应的Value,同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(可以理解为key唯一),允许多条记录的Value为Null。HashMap初始化容量为16,扩容每次为2*oldCap。HashMap是散列表实现,其内部是个Node类型的数组。数组中保存的有两种数据结构,第一种是链表,第二种是树形结构(红黑树)。除此之外HashMap不是线程安全的,不支持线程同步。
集合框架 - 图9

6.4.2.排序

HashMap的值是没有顺序的,它是按照key的HashCode来实现的。对于这个无序的HashMap可以参照TreeMap的value排序来实现排序。

  1. Map<String, String> map = new HashMap<String, String>();
  2. map.put("id_1", "my");
  3. map.put("id_2", "name");
  4. map.put("id_3", "is");
  5. map.put("id_4", "maxteng");
  6. List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
  7. Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
  8. //升序排序
  9. public int compare(Entry<String, String> o1,Entry<String, String> o2) {
  10. return o1.getValue().compareTo(o2.getValue());
  11. }
  12. });

6.5.TreeMap

6.5.1.简述

能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器。由于TreeMap是有序的,所以其除了实现了Map接口,还实现了SortedMap、NavigableMap接口,当用Iterator 遍历TreeMap时,得到是排序好的记录。TreeMap不允许key的值为null,初始化容量为0,TreeMap内部是红黑树的结构,不存在hash冲突的情况,所以不存在扩容的操作,除此之外TreeMap不是线程安全的,所以不支持线程同步。
集合框架 - 图10

6.5.2.排序

Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1小于、等于或者大于o2分别返回负整数、0或者正整数。

  1. Map<String, String> map = new TreeMap<String, String>(
  2. new Comparator<String>() {
  3. public int compare(String obj1, String obj2) {
  4. // 降序排序
  5. return obj2.compareTo(obj1);
  6. }
  7. });
  8. map.put("id_1", "my");
  9. map.put("id_2", "name");
  10. map.put("id_3", "is");
  11. map.put("id_4", "maxteng");

6.6.Hashtable

与HashMap类似,实现了Map接口,继承了AbstractMap类,因为是散列表实现(内部是数组+链表的结构),所以key和value的值均不允许为null,并且它支持线程的同步,内部方法使用关键字synchronized修饰,所以任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。Hashtable初始化容量为11,扩容每次为2*oldCap+1
集合框架 - 图11

6.7.集合使用

6.7.1.遍历Map

  1. Map<String,List<String>> map = new HashMap<>();
  2. for(Map.Entry<String, List<String>> tmp : map.entrySet()){
  3. String label = tmp.getKey();
  4. List<String> values = tmp.getValue()
  5. }

6.7.2.实体类与Map转换

6.7.2.1.实体类转Map

  1. import com.alibaba.fastjson.JSON;
  2. User user = new User();
  3. Map map = JSON.parseObject(JSON.toJSONString(user), Map.class);

6.7.2.2.Map转实体类

  1. User user = JSON.parseObject(JSON.toJSONString(map), User.class);

6.7.3.判断映射是否包含键值

6.7.3.1.判断映射是否包含指定键

containsKey
boolean containsKey(Object key)如果此映射包含指定键的映射关系,则返回 true。更确切地讲,当且仅当此映射包含针对满足 (key==null ? k==null : key.equals(k)) 的键 k 的映射关系时,返回 true。(最多只能有一个这样的映射关系)。

参数:
key - 测试是否存在于此映射中的键
返回:
如果此映射包含指定键的映射关系,则返回 true
抛出:
ClassCastException - 如果该键对于此映射是不合适的类型(可选)
NullPointerException - 如果指定键为 null 并且此映射不允许 null 键(可选)

实例:

  1. Map map = new HashMap<>();
  2. map.containsKey("test");

6.7.3.2.判断映射是否包含指定值

containsValue
boolean containsValue(Object value)如果此映射将一个或多个键映射到指定值,则返回 true。更确切地讲,当且仅当此映射至少包含一个对满足 (value==null ? v==null : value.equals(v)) 的值 v 的映射关系时,返回 true。对于大多数 Map 接口的实现而言,此操作需要的时间可能与映射大小呈线性关系。

参数:
value - 测试是否存在于此映射中的值
返回:
如果此映射将一个或多个键映射到指定值,则返回 true
抛出:
ClassCastException - 如果该值对于此映射是不合适的类型(可选)

7.Stream流