Java集合专题

本文深入探讨了Java集合框架,包括ArrayList、LinkedList、Vector、HashSet、LinkedHashSet、HashMap、TreeMap等的底层结构、源码分析及应用场景。强调了在多线程环境下集合的选择,分析了集合操作的效率差异,提供了多种遍历方式和实战练习,帮助开发者更好地理解和运用Java集合类。
摘要由CSDN通过智能技术生成

目录

集合的理解和好处:

数组:

写出Person数组扩容示意代码:

集合

集合的框架体系

Collection接口和常用方法

Collection接口实现类的特点

常用方法

注意:

Collection接口遍历元素的方式 1-使用Interator(迭代器)

 注意:

Collection接口遍历元素的方式 2-for循环增强

练习:

List接口和常用方法

List接口基本介绍

List接口的常用方法:

练习1:

List的三种遍历方式[ArrayList,LinkedList,Vector]

练习2:

ArrayList底层结构和源码分析

ArrayList的注意事项

ArrayList的底层操作机制源码分析(重点,难点)

ArrayList的底层操作机制分析案例

 注意:

 Vector底层结构和源码分析

Vector基本介绍

Vector的源码解读

Vector和ArrayList的比较

LinkedList的底层结构

LinkedList的全面说明

LinkedList的底层操作机制

LinkedList增删改查案例

ArrayList和LinkedList的比较

如何选择ArrayList和LinkedList:

Set接口和常用方法

Set接口基本介绍

 Set接口的常用方法

Set接口的遍历方式

Set接口的常用方法举例

HashSet的全面说明

 HashSet案例说明

HashSet底层机制说明

分析HashSet的添加元素底层是如何实现的?

HashSet练习1

HashSet练习2:

Set接口实现类-LinkedHashSet

LinkedHashSet的全面说明

说明:

LinkedHashSet练习:

Map

Map接口实现类的特点[很实用]

Map接口的遍历方法

Map练习:

Map实现类HashMap

HashMap小结

HashMap底层机制及源码分析

HashTable的基本介绍

 hashTable的应用案例:

Map接口的实现类-Properties

基本介绍

​编辑

总结-开发中如何选择集合实现类(记住)

Collections工具类

Collection工具类介绍

排序操作:(均为static方法)

查找、替换

homework01:

homework02:

homework03:

homework04:

homework05:

homework06:

 homework07:

集合主要包括:集合框架体系(在Java中的继承关系、接口和它的实现子类)、Collenction、Map、Collections

1、Collection接口,下面有两个重要的子接口:List接口(ArrayList、LinkedList、Vector)和Set接口(HashSet、LinkedHashSet、TreeSet)

2、Map接口,有5个常用的实现子类:HashMap、HashTable、LinkedHashMap、TreeMap、Properties.   

3、Collections工具类。

注:了解底层机制、看源代码、看JDK的底层实现、应用场景。

集合的理解和好处:

  • 数组:

  1. 长度开始时必须是指定的,而且一旦指定,不能修改。
  2. 保存的必须是同一类型的元素。
  3. 使用数组进行增加/删除元素比较麻烦。

写出Person数组扩容示意代码:

Person[] pers = new Person[1]; //长度为1

pers[0] = new Person();

//增加新的Person对象?

Person[] pers2 = new Person[pers.length+1]; // 创建一个新的数组

for(){}; //拷贝pers数组的元素到pers2数组中

pers2[pers2.length-1] = new Person(); //添加新的对象

  • 集合

  1. 可以动态保存任意多个对象(不同的数据类型),使用比较方便!
  2. 提供了一系列方便的操作对象的方法:add,remove,set,get等。
  3. 使用集合添加,删除新元素的示意代码-简洁明了

相当于是将底层代码写好了,我们需要哪种操作(增删改查)直接调用就好了。

比如新加一个元素,不用先创建一个新的数组再拷贝,然后再把新加的元素赋值到最后索引处。

集合的框架体系

Java的集合类有很多,主要分为两大类:【背下来】

         

注意:实线是继承,虚线是实现接口,UML规定的。

Collection是单例集合:存放单个对象;Map是双例集合:存放k-v。

Collection有两个重要的子接口,List和Set,他们的实现子类都是单例的。

Map接口的实现子类,都是双例集合,存放k-v。

        

 出现警告错误可以通过这个注解来抑制。

@SuppressWarnings({"all"}) 

Collection接口和常用方法

  • Collection接口实现类的特点

    • public interface Collection<E> extends Iterable<E>
  1. collection实现子类可以存放多个元素,每个元素可以是Object
  2. 有些Collection的实现类,可以存放重复的元素,有些不可以。
  3. 有些Collection的实现类,可以是有序的(List),也可以是无序的(Set)。
  4. Collection接口没有直接的实现子类,是通过的它的子接口Set和List来实现的。
  • 常用方法

  1. add:添加单个元素。 //list.add(元素);
  2. remove:删除指定元素。 //list.remove(元素/索引);
  3. contains:查找元素是否存在。  //list.contains(元素);
  4. size:获取元素的个数。//list.size();返回个数
  5. isEmpty:判断是否为空。 //list.isEmpty();  true/false;
  6. clear:清空。  //list.clear(); 清空集合
  7. addAll:添加多个元素。//
  8. containsAll:查找多个元素是否存在。
  9. removeAll:删除多个元素。

注意:

List list  = new ArrayList(); //这里的类型是父接口类型;
list.add("jack");
list.add(10);  //这里会自动装箱成Integer类型:list.add(new Integer(10));
list.add(true); //同上,会自动装箱成布尔;

System.out.println(list);

 我们可以知道,remove方法被重载了,当删除的是某个对象时,返回的是布尔型;

当删除的是索引,返回的是被删除索引处的值。

也就是当传int类型的5时,调用remove(int index);当传Integer类型的5时,是调用remove(Object o)

如果满足int类型就不会自动装箱成Integer。

 可以将一个集合快速拷贝到另一个集合。

  • Collection接口遍历元素的方式 1-使用Iterator(迭代器)

  • 基本介绍:
  1. Iterator对象成为迭代器,主要用于遍历Collection集合中的元素。
  2. 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
  3. Iterator的结构:(执行原理)
Interator interator = coll.iterator();  //得到一个集合的迭代器
//hasNext():判断是否有下一个元素
while(interator.hasNext()){
    //next(): 1.指针下移;2.将下移以后该指针位置的元素返回
    System.out.println(interator.next());
} 

     4.Iterator仅用于遍历集合,Iterator本身并不存放对象。

 注意:

在调用iterator.next()方法之前,必须要调用iterator.hasNext()进行检测。否则,当下一条记录无效时,直接调用iterator.next()会抛出NoSuchElementException异常

这里提一点,这里调用用iterator.remove()方法前,必须先调用iterator.next()越过要删除的元素

案例:CollectionInterator.java

public class CollectionIterator {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //接口类型指向子类
        Collection col = new ArrayList();

        col.add(new Book("三国演义","罗贯中",10.1));
        col.add(new Book("小李飞刀","古龙",10.1));
        col.add(new Book("红楼梦","曹雪芹",10.1));

        System.out.println("col = " + col);
        //遍历col
        //1.先得到 col 对应的 迭代器
        Iterator iterator = col.iterator();
        //2.使用while循环遍历即可。
        while(iterator.hasNext()){  //判断是否还有数据
            //返回下一个元素,类型是Object
            Object obejct = iterator.next();
            System.out.println("obejct = " + obejct);
         //这里默认调用的是toString方法。动态绑定的那个机制就会找到真正运行的类型
            //他的编译类型是Object,但是它的运行类型取决于真正存放时的类型。
            //快捷键是itit,,,ctrl+j可以找到当前的所有快捷键都展示出来
            //itco 迭代器定义和遍历
            //iter 增强for循环,
            //泛型只在编译器进行约束,在字节码看不出来。

        }
        //3.当退出while循环后,这时迭代器iterator指向最后一个元素
        //4.如果希望再次遍历,需要重置我们的迭代器
        iterator = col.iterator();
        System.out.println("第二次遍历------------");
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println("next = " + next);
        }
    }

}
  • Collection接口遍历元素的方式 2-for循环增强

        增强for循环,可以替代iterator迭代器,特点:增强for就是简化版的iterator,本质一样。

        只能用于遍历集合或数组

  • 基本语法:
for(元素类型 元素名:集合名或数组名){
    访问元素
}

案例:CollectionFor.java

 快捷键:iter  /  集合.for

public class CollectionFor {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        Collection col = new ArrayList();

        col.add(new Book("三国演义","罗贯中",10.1));
        col.add(new Book("小李飞刀","古龙",10.1));
        col.add(new Book("红楼梦","曹雪芹",10.1));

        //1.使用增强 for循环遍历,在 Collection集合中
        //2.增强 for,底层仍然是迭代器
        //3.增强 for可以理解成简化版的 迭代器遍历
        for (Object book : col) {
            System.out.println("book = " + book);
        }
        //增强for,也可以直接在数组中使用
//        int[] nums = {1,2,3,4,5};
//        for (int num : nums) {
//            System.out.println("num = " + num);
//        }
    }
}

练习:

请编写程序CollectionExercise.java

  1. 创建3个Dog{name,age}对象,放入到Array List对象中,赋值给list引用
  2. 用迭代器和增强for循环两种方式来遍历
  3. 重写Dog和toString方法,输出name和age。

so easy……

见案例:CollectionExercise.java

List接口和常用方法

  • List接口基本介绍

List接口是Collection接口的子接口 List.java

  1. List集合类中元素有序(即添加顺序和取出顺序一致)、元素且可重复。【案例】
  2. List集合中的每个元素都有其对应的顺序索引,即支持索引。【案例】
  3. List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  4. JDK API中List接口的实现类有:

        

        常用的有:ArrayList ,LinkedList和Vector.

  • List接口的常用方法:

        ListMethod.java

        List集合里添加了一些根据索引来操作集合元素的方法。

  1. void add(int index,Object ele):在index位置前插入ele元素。
  2. boolean addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来。
  3. Object get(int index):获取指定index位置的元素。
  4. int indexOf(Object obj):返回obj在集合中首次出现的位置。
  5. int lastIndexOf(Object obj):返回obj在集合中末次出现的位置。
  6. Object remove(int index):移除指定index位置的元素,并返回此元素。
    如果下标不存在,会抛出indexOutOfBoundsException;
  7. Object set(int index,Object ele):设置指定index位置的元素为ele,相当于是替换。
  8. List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合。‘[fromIndex,toIndex)’

练习1:

ListExercise.java

添加10个以上的元素(比如:String,“hello”),在2号位插入一个元素“蔡文姬”,获取第5个元素,删除第6个元素,修改第7个元素,再使用迭代器遍历集合。要求:使用List的实现类ArrayList完成。

so easy!

  • List的三种遍历方式[ArrayList,LinkedList,Vector]

        ListFor.java

  1. 方式一:使用iterator
  2. 方式二:使用增强for
  3. 方式三:使用普通for

说明:使用LinkedList完成,使用方式和ArrayList一样。

Stream遍历。 和list.foreach(e->sout(e));//foreach的简写

练习2:

ListExercise02.java

使用List的实现类添加三本图书,并遍历,打印如下效果;

名称:xx      价格:xx        作者:xx

名称:xx      价格:xx        作者:xx

名称:xx      价格:xx        作者:xx

要求:

  1. 按价格排序,从低到高。(使用冒泡法)
  2. 要求使用ArrayList、LinkedList、Vector三种集合实现。

实现Comparable<Book>,重写compareTo方法,调用Collections.sort(list); 

ArrayList底层结构和源码分析

  • ArrayList的注意事项

ArrayDetail.java

  1. permits all elements,including null,ArrayList可以加入null,并且多个null都是可以的。
  2. ArrayList是由数组来实现数据存储的。
  3. ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码,在多线程情况下,不建议使用ArrayList。多线程考虑Vector。
public class ArrayDetail {
    public static void main(String[] args) {

        //ArrayList是线程不安全的,看源码,没有synchronized关键字,(线程互斥)
        /**
         * public boolean add(E e) {
         *             ensureCapacityInternal(size + 1);  // Increments modCount!!
         *         elementData[size++] = e;
         *             return true;
         *         }
         */
        ArrayList arrayList = new ArrayList();
        arrayList.add(null);
        arrayList.add("tom");
        arrayList.add(null);
        System.out.println("arrayList = " + arrayList);
    }
}

  • ArrayList的底层操作机制源码分析(重点,难点)

        ArrayListSource.java    先说结论,再分析源码

  1. ArrayList中维护了一个Object类型的数组elementData.java  [debug 看源码]  
    transient Object[] elementData;  
    //transient 表示瞬间,短暂的。表示该属性不会被序列化。
    //序列化就是持续保持,保存到硬盘上
    //Java序列化就是指把Java对象转换为字节序列的过程
    //Java反序列化就是指把字节序列恢复为Java对象的过程。
    
  2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData的容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
  3. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
  • ArrayList的底层操作机制分析案例

        ArrayListSource.java

ArrayList arrayList = new ArrayList();

        //使用for循环给list集合添加1-10个数据
        for (int i = 0; i < 10; i++) {
            arrayList.add(i);
        }
        //使用for循环给list集合添加11-15个数据
        for (int i = 11; i < 15; i++) {
            arrayList.add(i);
        }
        arrayList.add(100);
        arrayList.add(200);
        arrayList.add(null);
    }

无参:

 

 注意:

//注意:Idea默认情况下,Debug显示的数据是简化后的,即不显示为null的部分,
//如果想要看到,需要做设置。

看到的信息就会比较全了。debug非常好用。 

有参:

 Vector底层结构和源码分析

  • Vector基本介绍

        Vector_.java

  1. Vector类的定义说明
  2. Vector底层也是一个对象数组,proctected Object[] elementData;
  3. Vector是线程同步的,即线程安全。Vector类的操作方法带有synchronized(支持线程同步和互斥)
  4. 在开发中,需要同步安全时,考虑使用Vector。

 除了List接口,它还实现了

 开发一般用JUC包中绝对线程安全的集合Vector只是相对安全,add、remove这些方法不是原子操作,所以还是别用Vector。

只有一个线程,建议使用ArrayList,因为效率高。如果多线程,建议使用Vector,因为它是安全的。

只有卷,才能筛!!!

  • Vector的源码解读

Vector和ArrayList的比较

Vector是线程同步的,所以每个方法都会做安全校验。

@SuppressWarnings({"all"})
public class Vector_ {
    public static void main(String[] args) {
        //无参构造
//        Vector vector = new Vector();
        //有参数的构造
        Vector vector = new Vector(8);
        for (int i = 0; i < 10; i++) {
            vector.add(i);
        }
        vector.add(100);
        System.out.println("vector = " + vector);
        /**
         * 1.  public Vector() {
         *         this(10);
         *     }
         *
         *     补充:如果是 Vector vector = new Vector(8);
         *     走的方法:
         *     public Vector(int initialCapacity) {
         *         this(initialCapacity,0);
         *     }
         *     这个0的参数叫扩容增量,如果这个增量大于0,扩容后的容量就是 原容量+增量,否则就是 原容量+原容量
         *  2.vector.add(i);
         *  2.1 //下面这个方法是添加数据到vector集合
         *  public synchronized boolean add(E e) {
         *         modCount++;
         *         ensureCapacityHelper(elementCount + 1);
         *         elementData[elementCount++] = e;
         *         return true;
         *     }
         *
         *  2.2 确定是否需要扩容
         *  ensureCapacityHelper(elementCount + 1);
         *  private 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chao_nengli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值