概述

  1. 集合在JDK java.util.* 包下

所有集合类和集合接口都在

  1. 集合是一个载体,一个容器,一次可以容纳多个对象
  2. 集合里存的是对象的内存地址
  3. 集合本身也是一个对象(有内存地址)
  4. 集合里可以存集合
  5. 不同的集合底层对应不同的数据结构
  6. 集合中不能直接存储基本数据类型,他会自动的帮你装箱

集合的理解和好处

之前保存数据都是用的数组,那么数组有不足的地方,分析如下:
数组缺点:

  • 长度开始时必须指定,而且一旦指定,不能更改
  • 保存的必须为同一类型的元素
  • 使用数组进行增加元素的示意代码 - 比较麻烦 ```java // 写出Person数组扩容示意代码 Person[] pers = new Person[1]; // 大小是1 per[0] = new Person();

// 此时数组已满,增加新的person对象: Person[] pers2 = new Person[pers.length + 1]; for(){} // 循环将pers数组的东西拷进去 pers2[1] = new Person();

// 第二种数组拷贝的方法 使用System.arraycopy()方法 // 源数组 Integer[] integers = new Integer[5]; for (int i = 0; i < integers.length; i++){ integers[i] = i; } // 新的目标数组 Integer[] newIntegers = new Integer[10]; // 参数 1.拷贝源, 2.源的起点, 3.目标, 4.目标的起点, 5.要拷贝多长 // 新的数组中,没有被使用的元素为 null System.arraycopy(integers,0,newIntegers,0,integers.length);

  1. <a name="OSstX"></a>
  2. ## 集合概念
  3. 1. 可以**动态保存**任意多个对象,使用比较方便。
  4. 1. 提供了一系列方便的操作对象的方法:add(),remove(),set(),get()
  5. 1. 使用集合添加,删除新元素的实例代码更加间接明了
  6. <a name="fxHas"></a>
  7. ## 在java中集合分为两大类:
  8. - 一类是单个方式存储元素:
  9. - **单个方式存储元素**,这一类集合中超级父接口:java.util.**Collection**;
  10. - 一类是以**键值对儿**的方式存储元素
  11. - **以键值对的方式存储元素**,这一类集合中超级父接口:java.util.**Map**;
  12. <a name="93Kih"></a>
  13. # Collection
  14. 1. Collection 是集合里面的超级父接口
  15. 1. Collection可以存储那些元素
  16. 在没有使用泛型的情况下可以存储Object所有子类<br />使用了泛型,只能存储某个具体的类型<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21770825/1630681527483-dd551028-154e-417a-8673-36c25f072d5e.png#clientId=u2db95756-3657-4&from=paste&id=u5997bfea&margin=%5Bobject%20Object%5D&name=image.png&originHeight=553&originWidth=670&originalType=binary&ratio=1&size=31870&status=done&style=none&taskId=u40da7645-a219-49a2-942b-7454fa12fa3)
  17. <a name="u7FEX"></a>
  18. ### Collection 继承图
  19. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/21770825/1630681704914-08a87301-3217-466b-b2f0-1137813b40cf.png#clientId=u2db95756-3657-4&from=paste&id=u83f02d1f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=775&originWidth=1154&originalType=binary&ratio=1&size=320550&status=done&style=none&taskId=u7f9c6b82-8c44-44e5-aa89-fbce9a4ef29)
  20. <a name="BMsEi"></a>
  21. # Collection接口和常用方法
  22. <a name="cMQCU"></a>
  23. ### 1)Collection接口实现类的特点
  24. 1. collection实现子类可以存放多个元素,每个元素可以是Object
  25. 1. 有些Collection的实现类,可以存放重复的元素,有些不可以
  26. 1. 有些Collection的实现类,有些事有序的 List, 有些不是有序的Set
  27. 1. Collection接口没有直接的实现子类,是通过他的子接口Set和List来实现的。
  28. <a name="ztJOc"></a>
  29. ### 2)常用方法
  30. 1. **add**(元素) 添加一个元素
  31. 1. **remove**(元素) 删除一个元素,返回一个boolean || **remove**(索引) 返回被删除的元素
  32. 1. **contains**(元素) 查找该元素是否存在
  33. 1. **size**() 获取元素个数
  34. 1. **isEmpty**() 判断是否为空
  35. 1. **clear**() 清空
  36. 1. **addAll**(Collection对象) 添加多个元素
  37. 1. **containsAll**(Collection对象) 查找多个元素
  38. 1. **removeAll**(Collection对象) 删除多个元素
  39. ```java
  40. // 创建一个集合
  41. Collection collection = new ArrayList();
  42. // add() 添加一个元素
  43. collection.add(1);
  44. collection.add(2);
  45. // remove()删除指定元素
  46. collection.remove(1);
  47. // contains() 查找元素是否存在
  48. boolean contains = collection.contains(2);
  49. // size() 获取元素个数
  50. int size = collection.size();
  51. // isEmpty() 判断是否为空
  52. boolean empty = collection.isEmpty();
  53. // clear() 清空集合
  54. collection.clear();
  55. // addAll() 添加多个元素
  56. Collection collection1 = new ArrayList();
  57. collection1.add(11);
  58. collection1.add(22);
  59. collection1.add(33);
  60. collection.addAll(collection1);
  61. // containsAll(Collection对象) 查找多个元素是否都存在
  62. boolean b = collection.containsAll(collection1);
  63. // removeAll(Collection对象) 删除多个元素
  64. collection.removeAll(collection);

注意
  • 集合中存储的都是引用地址,往里面存入1 实则是存入 new Integer(1); 自动装箱

3)Collection接口遍历元素方式1 - itreator

基本介绍

  1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素
  2. 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,既可以返回一个迭代器。
  3. Itreator 仅仅用来遍历集合,Iterator本身并不存放对象。

List/Set/SortedSet特点

image.png
集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,
集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)
list.add(100); //自动装箱Integer
注意:

  • 集合在java中本身是一个容器,是一个对象
  • 集合中任何时候存储的都是“引用”

List

特点

  • 有序
  • 可重复
  • 有下标 0开始 以1递增

List接口为Collection的子接口,也就是说Collection中有的方法,这里都有

创建集合 List l = new ArrayList(); 多态

List集合常用方法

void add(下标,元素) //在指定的位置插入元素

Object get(下标) //得到指定位置的元素

int indexOf("元素") //得到该元素第一次出现的下标

int lastIndexOf("元素") //得到该元素最后一次出现的下标

Object remove(下标) // 删除指定位置的元素

Object set(下标,元素) //修改指定下标的元素

链表

优点
随机增删元素效率较高
缺点
查询效率底
在开发中如果遇到了随机增删元素较多的业务时,建议使用LinkedList

ArrayList

  • ArrayList集合初始化容量10
  • 扩容为原容量1.5倍
  • 底层是数组

    Vector

  • Vector初始化容量是10

  • 扩容为原容量的2倍
  • 底层是数组
  • Vector底层是线程安全的

  • 怎么得到一个线程安全的List

  • Collections.synchronizedList(list)

集合的遍历/迭代器

此内容只能在Collection中使用Map集合不能使用

Iterator i = 集合.iterator(); // 拿到迭代器

迭代器常用方法
boolean hasNext()
如果返回true表示有元素可以迭代
如果返回false表示没有元素可以迭代
Object next();
让迭代器前进一位,并且拿到该元素
迭代器对象最初没有指向任何元素

遍历集合

Collection c = new ArrayList(); // 创建集合 多态
Iterator i = c.iterator(); //拿到迭代器
while(i.hasNext()){ //如果有元素返回true ,执行循环,没有则退出
    System.out.println(i.next()); // 迭代
}

注意

  1. 当集合发生结构变化,一定要重新获取迭代器
  2. 在迭代元素时不能调用c.remove()方法 ,删除元素但是可以调用i.remove()方法 ,删除元素

泛型

在JDK5.0出现的新特性

List myList = new ArrayList<>(); <>钻石表达式
使用泛型后myList集合中只允许出现Animal类或者他的子类
优点
使用泛型后,集合中的数据类型更加统一
缺点
导致集合中的储存元素缺乏多样性
注意
使用泛型之后迭代器迭代的就不是Object类型了而是<> 这里面的类型


Set / Vector

  1. 底层是TreeMap
  2. TreeMap底层是二叉树
  3. 放到TreeSet集合中的元素 等同于放到TreeMap的key部分
  4. 特点

无序不可重复
自动排序,从小到大

排序可以自定义

比较规则
升序 : return this.age-c.age;
降序 : return c.age - this.age;
例如

    TreeSet<B> treeSet2 = new TreeSet<>(new Comparator<B>() {
        @Override
        public int compare(B b, B t1) {
            return b.age - t1.age;
        } //匿名内部类
    });

    treeSet2.add(new B(520));
    treeSet2.add(new B(500));
    treeSet2.add(new B(510));
    treeSet2.add(new B(400));
    treeSet2.add(new B(300));

    for ( B b : treeSet2){
        System.out.println(b);
    }

结论

  1. 放到TreeSet或者TreeMap集合中key部分想要排序包括两种方式
    • 集合中的元素类中实现Comparable接口
    • 在构造的时候传一个比较器Comparator接口(对象)
  2. 如果比较规则不变使用Comparable接口
  3. 如果比较规则有多个,需要切换,用Comparator接口(匿名内部类)

Vector 集合

  • 底层是数组
  • 初始容量为10
  • 扩容之后是原容量的2倍 10—>20—>40
  • 所有的方法都是线程同步的(所以不常用)

Map

概念

Map集合以key和value的方式储存数据(键值对)

  1. key和value是引用数据类型
  2. key和value保存的是对象的内存地址
  3. key起主导作用,value是附属品

    Map集合常用方法

  4. put(k,v) //向Map集合中添加键值对

  5. get(Object key) // 通过key找到value
  6. void clear() //清空集合
  7. boolean containsKey(Object key) // 判断集合里有没有key(只在key中找)
  8. boolean contiansValue(Object value) //判断集合中有没有value(只在value中找)
  9. boolean isEmpty() //判断集合是否为空
  10. int size() //获取键值对的数量,一组为一个
  11. remove (Object key) // 通过key来删除键值对
  12. Collection values() // 得到所有的value元素 用一个Collection 集合接收
  13. Set keySet() //得到所有的key元素 用Set集合接收

哈希表数据结构(散列表)

  1. 哈希表是数组和单向链表的结合体
  2. 哈希表就是将传进来的key元素,通过hashCode算出来一个下标,将key存进去
  3. 如果重写hashCode方法返回都是一样的值,那么就变成了纯链表
  4. 如果重写的hashCode方法返回的值都不一样,那么就变成了纯数组
  5. 如果put(k重复了,value会覆盖)

    重点

  • 放在HashMap/HashSet集合里key部分的元素必须同时重写HashCode()和equals()
  • hashCode()和equals()方法不需要自己写直接idea生成
  • HashMap集合初始化容量必须是2的次幂,这也是官方推荐 【推荐16】

Map 继承图

image.png
image.png

HashMap

  • HashMap集合的默认初始化容量为16,默认加载因子为0.75
  • 默认加载因子是指HashMap集合底层数组的容量达到75%以后开始扩容

Properties

继承Hashtable
key和value都只能存String
属性类对象(线程安全)

setProperty(k,v) //存元素
getProperty(k); //通过key得到value

自平衡二叉树

遵循左小右大的原则存放

遍历

前序遍历 根左右
中序遍历 左根右
后序遍历 左右根


Map集合遍历

  1. 通过获取所有的key,通过遍历key,来遍历value

     Map<Integer,String>map = new HashMap<>();
     map.put(1,"张三");
     map.put(2,"李四");
     map.put(3,"王五");
     Set set = map.keySet(); // 得到所有的key元素
     Iterator it = set.iterator(); //拿到迭代器
     while(it.hasNext()) {
         Integer i = (Integer) it.next(); // 得到迭代的key
         String i1 = map.get(i); //通过得到迭代的key 得到value
         System.out.println(i);
         System.out.println(i1);
     }
    
  2. 增强for

     Map<Integer,String>map = new HashMap<>();
     map.put(1,"张三");
     map.put(2,"李四");
     map.put(3,"王五");
     Set<Integer> set = map.keySet(); // 得到所有的key元素
     for(Integer i : set){
         System.out.println(i+"="+map.get(i));
    
     }
    
  3. 大数据量时使用

     Set<Map.Entry<Integer,String>> set1 = map.entrySet();
    
     for (Map.Entry<Integer,String> node :set1){
         System.out.println(node.getKey()+"="+node.getValue());
     }
    

    Map总结

  4. ArrayList 底层是数组

  5. LinkedList 底层双向链表
  6. Vector 底层是数组,线程安全 效率底,使用较少
  7. HashSet 底层是HashMap,放在HashSet集合中的元素,相当于放在HashMap的key部分
  8. TreeSet 底层是TreeMap,放到TreeSet集合里的元素等同于放在TreeMap集合中的key部分
  9. HashMap 底层是哈希表
  10. Hashtable 底层是哈希表,线程安全,效率低,使用少
  11. Properties 线程安全 并且key和value中只能存储字符串 String
  12. TreeMap 底层是二叉树,TreeMap集合中的key可以自动按照从小到大的顺序排序

image.png