一、Java集合概述

1.集合简介

Java集合类可以用于存储数量不等的多个对象,并可以实现常用的数据结构,如栈、队列等。除此之外,Java集合还可以用于保存具有映射关系的集合。集合类也被称为容器类,都位于java.util包下。

  • 集合、数组都是对多个数据进行存储操作的结构,简称Java容器,集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);而集合里只能保存对象的引用(一般说保存对象)。
  • 数组在存储多个数据方面的特点:

(1)一旦初始化,长度便确定。
(2)数组一旦定义好,其元素的类型也就确定了。

  • 数组在存储多个数据时的缺点:

(1)一旦确定,长度不可修改。
(2)数组中提供的方法非常有限,对于增删、插入数据等操作非常不便,且效率不高。
(3)对于获取数组中实际元素个数,数组无现成的属性或方法可用。
(4)数组有序、可重复存储,对于无序、不可重复存储无法满足。

  • Java集合分为Collection和Map两大体系:

(1)Collection接口:存储单列数据,定义了存取一组对象的方法的集合,主要分为List和Set,其中List是元素有序、可重复的集合,Set是元素无序、不可重复的集合。
(2)Map接口:存储双列数据,保存具有映射关系“key—value”的集合。

2.集合体系的继承树

image.png
image.png

3.实现类总结

  • ArrayList:底层是数组,
  • LinkedList:底层是双向链表,
  • Vector:底层是数组,线程安全的,效率较低,使用较少。
  • HashSet:底层是HashMap,放到HashSet集合里的元素等同于放到HashMap集合的key部分。
  • TreeSet:底层是TreeMap,放到TreeSet集合里的元素等同于放到TreeMap集合的key部分。
  • HashMap:底层是哈希表,
  • Hashtable:底层是哈希表,线程安全的,效率较低,使用较少。
  • Properties:线程安全的,并且key和value只能存储字符串String。
  • TreeMap:底层是二叉树,TreeMap集合里的key可以自动按照大小顺序排序。

List集合存储元素的特点:有序可重复,存进去的顺序和取出来的顺序相同,元素有下标。
Set集合存储元素的特点:无序不可重复,存进去的顺序和取出来的顺序不相同,元素无下标。
SortedSet集合存储元素的特点:无序不可重复,但是该集合中的元素是可排序的。
往Set集合中放数据,实际上放到了Map集合中的key部分。

二、Collection和Iterator接口

1.Collection接口中的常用方法

image.png
注:没有使用泛型之前,Collection中可以存储Object的所有子类型。在使用泛型后,只能存储某个具体的类型。

  1. public class Test {
  2. public static void main(String[] args) {
  3. //Collection c = new Collection();//接口无法实例化
  4. Collection c = new ArrayList();//多态,父类引用指向子类对象
  5. c.add(100);//自动装箱,实际上存储的是对象的引用
  6. c.add("ABC");
  7. c.add(new Object());
  8. System.out.println(c.size());//获取集合中的元素个数,3
  9. boolean flag = c.contains(100);//判断是否包含100
  10. System.out.println(flag);//true
  11. c.remove("ABC");//删除ABC
  12. c.clear();//清空整个集合
  13. System.out.println(c.isEmpty());//true
  14. }
  15. }

2.Collection集合迭代

注:这里所讲的迭代方式是所有Collection通用的一种方式,在Map集合中不能使用,只能在Collection集合及其子类中使用。迭代器必须依附于Collection对象,有一个迭代器,必然有一个与之关联的Collection对象。

2.1 迭代器中的三个方法

  • boolean hasNext():如果仍有元素可迭代,返回true。
  • Object Next():让迭代器指向下一位,并返回指向的元素。
  • void remove():删除集合里上一次next方法返回的元素。

    1. public class Test {
    2. public static void main(String[] args) {
    3. Collection c = new ArrayList();
    4. c.add(100);
    5. c.add("ABC");
    6. c.add(new Object());
    7. //对集合Collection迭代
    8. //第一步:获取迭代器对象
    9. Iterator it = c.iterator();
    10. //第二步:通过迭代器对象开始遍历集合
    11. while (it.hasNext()){
    12. Object obj = it.next();
    13. System.out.println(obj);
    14. }
    15. }
    16. }
    17. 100
    18. ABC
    19. java.lang.Object@119d7047

    2.2 迭代步骤

  • 获取迭代器对象

  • 使用迭代器对象中的方法开始遍历集合

    3.使用foreach遍历集合

    ```java foreach(元素类型 变量名 : 数组或集合){

}

  1. ```java
  2. public class Test {
  3. public static void main(String[] args) {
  4. List<Integer> list = new ArrayList<>();
  5. list.add(1);
  6. list.add(2);
  7. list.add(3);
  8. for (Integer data : list) {
  9. System.out.println(data);
  10. }
  11. }
  12. }

4.深入contains方法

  1. public class Test {
  2. public static void main(String[] args) {
  3. Collection c = new ArrayList();
  4. String s1 = new String("abc");
  5. c.add(s1);
  6. String x = new String("abc");
  7. System.out.println(c.contains(x));//思考是否包含?
  8. }
  9. }
  10. }

contains方法底层调用了equals方法,在这里String类的equals方法比较的是内容,而不是内存地址,所以上述代码的结果为:true。
这里要注意,如果是自己定义的类,要重写equals方法比较的才是内容,不然调用equals比较的是地址。

5.深入remove方法

remove方法在底层同样调用了equals方法,如果自己没有重写equals方法,则在删除元素时,只会按地址删除,而不是按内容删除。

  1. public class Test {
  2. public static void main(String[] args) {
  3. Collection c = new ArrayList();
  4. String s1 = new String("abc");
  5. c.add(s1);
  6. String s2 = new String("abc");
  7. c.remove(s2);//s1和s2内容相同,在这里,s1就是s2
  8. System.out.println(c.size());//0
  9. }
  10. }

6.迭代器注意事项

集合结构发生改变,一定要重新获取迭代器,因为迭代器只对应某一个时刻的状态,如果集合发生了改变,迭代器没有重新获取时,调用next()方法会报ConcurrentModificationException异常。直接通过集合去删除元素,迭代器不知道,迭代器不会更新;而通过迭代器去删除元素,迭代器会自动更新。所以,在迭代过程中,一定要使用迭代器的remove()方法删除元素,而不要使用集合自带的remove()方法删除元素。

  1. public class Test {
  2. public static void main(String[] args) {
  3. Collection c = new ArrayList();
  4. Iterator it = c.iterator();//此时获取的是集合中没有元素状态下的迭代器
  5. c.add(1);
  6. c.add(2);
  7. c.add(3);
  8. //异常:ConcurrentModificationException,集合发生改变但未重新获取迭代器
  9. while(it.hasNext()){
  10. System.out.println(it.next());
  11. }
  12. }
  13. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Collection c = new ArrayList();
  4. c.add(1);
  5. c.add(2);
  6. c.add(3);
  7. Iterator it = c.iterator();
  8. while(it.hasNext()){
  9. Object o = it.next();
  10. c.remove(o);//删除元素,集合发生改变,但迭代器未重新获取
  11. System.out.println(o);
  12. }
  13. }
  14. }
  15. //ConcurrentModificationException异常,删除元素后集合发生改变,在下一次循环时为重新获取迭代器
  1. public class Test {
  2. public static void main(String[] args) {
  3. Collection c = new ArrayList();
  4. c.add(1);
  5. c.add(2);
  6. c.add(3);
  7. Iterator it = c.iterator();
  8. while(it.hasNext()){
  9. Object o = it.next();
  10. it.remove();//删除迭代器指向的元素,迭代器会自动更新
  11. System.out.println(o);
  12. }
  13. }
  14. }