一、集合的由来和基本理解:

理解:集合就是一种容器,可以存放任意数量的拥有共同属性的对象。

集合和数组的区别:

  1. 长度区别: 数组的长度是固定的而集合的长度是可变的。
  2. 存储数据类型的区别:数组可以存储基本数据类型 , 也可以存储引用数据类型; 而集合只能存储引用数据类型。
  3. 内容区别: 数组只能存储同种数据类型的元素 ,集合可以存储不同类型的元素。

二、Java中集合常用的分类:Collection 和 Map

java 知识 集合 java集合的了解_java

1. Collection类的常用功能:

常用的功能有:添加、删除、判断、获取、长度、交集等功能。

方法

功能

boolean add(Object obj)

添加一个元素

boolean addAll(Collection c)

添加一个集合的元素

void clear():

移除所有元素

boolean remove(Object o):

移除一个集合的元素(返回值代表集合中的元素有没有发生改变) 移除的元素是两个集合的交集元素

boolean contains(Object o)

判断集合中是否包含指定的元素

boolean containsAll

判断集合中是否包含指定的集合元素,全部包含,返回ture

boolean isEmpty()

判断集合是否为空

Iterator iterator()

迭代器获取元素

int size()

获取集合长度

boolean retainAll(Collection c)

获取两个集合的交集元素,覆盖调用该方法的集合

Object[] toArray()

把集合转换为数组

2. Collection的遍历方式:

Iterator 迭代器遍历集合元素
Iterator 迭代器是一种仅限于遍历集合类的工具,所有集合都实现了Iterator接口。Iterator本身并不提供承装对象的能力,如果需要创建Iterator对象,则必须有一个被迭代的集合。接收时应该返回一个对象。
Iterator的内部相当于指针,通过hasNext() 和 next() 不断的在集合中移动位置,把集合中的值赋给iterator,通过iterator.next() 方法取出。

iterator.hasNext():  判断是否存在下一个元素
iterator.next():  接收该元素

Iterator iterator = list.iterator();  //通过迭代器,获取集合元素
while (iterator.hasNext()){  //iterator.hasNext()判断是否存在下一个元素
Object object = iterator.next();   //iterator.next()接收该元素
System.out.println(object); }

② ListIterator 迭代器遍历集合元素:
ListIterator继承自Iterator,ListIterator还有许多自身的额外功能。

boolean hasPrevious():  是否存在前一个元素
E previous(): 返回列表中的前一个元素

ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object o1 = listIterator.next();
System.out.println(o1); }  //完成反向遍历之前,要先进行正向遍历

while (listIterator.hasPrevious()){
Object object2 = listIterator.previous();
System.out.println(object2); }

注意:以上两个方法可以实现反向遍历,但是注意要完成反向遍历之前,要先进行正向遍历,这样指针才能移到最后;如果直接反向遍历是没有效果的,因为指针默认位置就在最前面,而最前面没有元素。

ConcurrentModificationException异常出现问题

问题:当我们用Iterator这个迭代器遍历采用hasNext方法和next方法,集合修改集合,会出现并发修改异常。
原因:是我们的迭代依赖于集合 当我们往集合中添加好了元素之后,获取迭代器,那么迭代器已经知道了集合的元素个数,这个时候你在遍历的时候又突然想给 集合里面加一个元素(用的是集合的add方法),而迭代器此时并不知道,就报错了。
解决:我们用ListIterator迭代器遍历,用迭代器自带的add方法添加元素,那就不会报错了。

add(E e) 将指定元素插入列表(可选操作)
set(E e): 用指定元素替换next() 或 previous() 返回的最后一个元素(可选操作)

Foreach 循环遍历集合元素:可以输出数组或集合。

for的形式:for(int i=0;i<arr.size();i++){...}

 foreach的形式: for(int i:arr){...}
1. Map类的常用功能:

Map接口 和 Collection接口的区别:

  1. Map是双列的,Collection是单列的
  2. Map的键唯一,Collection的子体系Set是唯一的
  3. Map集合的数据结构针只对键有效,跟值无关;Collection集合的数据结构是针对元素有效

常用的功能有:添加、删除、判断、获取、长度等功能。

方法

功能

V put(K key,V value)

添加一个元素

void clear():

移除所有的键值对元素

boolean containsKey(Object key):

判断集合是否包含指定的键

boolean containsValue(Object value)

判断集合是否包含指定的值

boolean isEmpty()

判断集合是否为空

Set<Map.Entry<K,V>> entrySet()

返回一个键值对的Set集合,常用于遍历Map

V get(Object key):

根据键获取值

Set keySet():

获取集合中所有键的集合

int size():

返回集合中的键值对的对数

注意:
V put(K key,V value):添加元素。这个其实还有另一个功能——替换。
如果键是第一次存储,就直接存储元素,返回null。
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值。

2. Map的遍历方式:

①Set keySet():获取集合中所有键的集合
思想说明:将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取key 。
取到的结果会乱序,是因为取得数据行主键的时候,使用了HashMap.keySet()方法,而这个方法返回的Set结果,里面的数据是乱序排放的。

HashMap<String, String> hashMap = new HashMap();
hashMap.put("黄晓明","杨颖");
hashMap.put("陈思诚","佟丽娅");
hashMap.put("杜江","霍思燕");
hashMap.put("章子怡","汪峰");
Set<Map.Entry<String,String>> entries = hashMap.entrySet();
for(Map.Entry<String,String> entry : entries){
String s1 = entry.getKey();
String s2 = entry.getValue();
System.out.println(s1+"===="+s2);}

②Set<Map.Entry<K,V>> entrySet():获取集合中所有键值对的集合

Set<Map.Entry<K,V>> entrySet() 方法,返回此映射中包含的映射关系的 Set 视图。(一个关系就是一个键-值对),就是把(key-value)作为一个整体一对一对地存放到Set集合当中的。Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()两种方法来取key和value。返回的是Entry接口。

总结:更推荐使用第二种方法,因为第二种方法效率高。
entrySet() 方法访问一次就可将键值对存在在Set集合中,而keySet() 方法,相当于间接的访问了两次。

三、 重要接口和类的介绍。

Collection集合:

1. List接口特点:(有序,可重复)

List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。

List类

特点

ArrayList

底层数据结构是数组,查询快,增删慢。线程不安全,效率高。

Vector:

底层数据结构是数组,查询快,增删慢。线程安全,效率低。

LinkedList

底层数据结构是链表,查询慢,增删快。线程不安全,效率高。

特别说明:
ArrayList去除集合中自定义对象元素的重复值(对象的成员变量值相同),需要重写equals()方法。

用List集合特有的get()方法,结合for循环可进行遍历。

List list = new ArrayList();
for(int i = 0; i < list.size();i++){
Object object3 = list.get(i);
System.out.println(object3);  }

集合的**size( )**是集合的有效值长度
ArrayList删除元素时,注意:
在代码中,删除元素后,需要把下标减一。这是因为在每次删除元素后,ArrayList会将后面部分的元素依次往上挪一个位置(就是copy),所以,下一个需要访问的下标还是当前下标,所以必须得减一才能把所有元素都遍历完。

ArrayList al = new ArrayList();
al.add("a");
al.add("b");
al.add("b"); 
al.add("c"); 
for (int i = 0; i < al.size(); i++) {
    if (al.get(i) == "b") {
        al.remove(i);
        i--;//一定要移动下标,不然会报错
    }
}
2. Set接口特点:(无序,不重复)

Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。

List类

特点

HashSet

保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。

LinkedHashSet:

并且唯一,元素有序

TreeSet

元素唯一,并且可以对元素进行排序。提供两种排序方法:自然排序和使用比较器排序

特别说明:
HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。

HashSet :底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null。
哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) 。
当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
HashSet 集合判断两个元素相等的标准:
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

LinkedHashSet 数据结构有两个:链表和哈希表,链表保证有序 哈希表保证元素唯一。

TreeSet 集合里的元素唯一,并且可以对元素进行排序。提供两种排序方法:自然排序和使用比较器排序。到底使用的是哪一种的排序取决于,构造方法。

使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素
必须实现Comparable接口 否则无法进行自然排序。
保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等,则不重复存储。

排序原理:底层是二叉树的数据结构,先存入一个树根,分两个叉,存储元素时 跟树根比较,小的放在左边,大的放在右边,如果相等就不存储。取的时候按照 左中右的顺序来取。

比较器排序:采用的是有参构造,参数要一个比较器
TreeSet(Comparator < ? super E > comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。
java.util 接口 Comparator
int compare (T o1, T o2) 比较用来排序的两个参数。
用匿名内部类的方式来传一个比较器。

TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getTotal() - s2.getTotal();
            }
        });

Map集合:(键值对、键唯一、值不唯一)

Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。

Map类

特点(Map数据结构只与键有关)

HashMap

HashMap是最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。因为键对象不可以重复,所以HashMap最多只允许一条记录的键为Null,允许多条记录的值为Null,是非同步的

Hashtable

Hashtable与HashMap类似,是HashMap的线程安全版,它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,它继承自Dictionary类,不同的是它不允许记录的键或者值为null,同时效率较低。

ConcurrentHashMap

线程安全,并且锁分离。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

LinkedHashMap

底层的数据结构是链表和哈希表,元素有序,并且唯一。元素的有序性由链表数据结构保证 唯一性由 哈希表数据结构保证

TreeMap

键的数据结构是红黑树,可保证键的排序和唯一性。排序分为自然排序和比较器排序。线程是不安全,效率比较高

总结:对集合类的学习需要注意两点:

1. 注意理清集合之间的关系,掌握每一种集合的特点,理解不同集合之间的区别。
2. 多做题,熟练应用各种集合的常用方法,根据需求,结合集合特点,使用合适的集合。