集合介绍和 LIst 集合

一. 对象数组的概述和使用

  1. 案例演示

    • 需求: 创建5个学生对象, 将对象存入到数组中,遍历数组,打印学生信息
    public static void main(String[] args) {
    	Student[] sts = new Student[5];
    	
    	sts[0] = new Student("小红", 18);
    	sts[1] = new Student("小明", 19);
    	sts[2] = new Student("小白", 20);
    	sts[3] = new Student("小辉", 21);
    	sts[4] = new Student("小张", 23);
    	
    	for (int i = 0; i < sts.length; i++) {
    		System.out.println(sts[i]);
    	}
    }
    
  2. 解析

    • 数组中存放的是对象的地址值
    • 遍历数组时就可以拿到引用地址值,调用对象完成方法

二. 集合概述

  1. 概述

    • 我们都知道,数组的长度是不可变的, 当元素的个数超过数组的长度之后, 我们就只能通过创建长度更长的新数组的方式来存储元素, 太麻烦了
    • 集合给我提供另外一种容器的概念,可变长度的容器, 这样,程序在使用的时候就不需要再考虑容器容量的问题,从而可以更加专心于业务
    • 我们要知道,java中数组是唯一的底层容器,所有, 集合是开发者使用java规范制作的逻辑上的容器
  2. 数组和集合的区别

    • 区别1
      • 数组既可以存储基本数据类型, 又可以储存引用数据类型,基本数据类型存储的是值, 引用数据类型储存的是地址值
      • 集合只能存储引用数据类型(对象的引用), 其实集合也可以存储基本数据类型, 但是在存储的时候自动装箱变成包装类对象
    • 区别2
      • 数组长度是固定的,不能自动增长
      • 集合的长度的是可变的,可以根据元素的增加而增长
  3. 使用场景

    • 如果元素的个数是固定的,推荐使用数组
    • 如果元素的个数不固定,推荐使用集合(日常开发中,使用集合比较普遍)
  4. 集合体系图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xDjMyc2Y-1619488505722)(集合体系图.jpg)]

  5. 集合分类

    • Collection集合
      • 单列集合, 直接存储对象的引用
    • Map集合
      • 双列集合, 使用key-value的形式, 每个元素会有一个唯一的名称

三. Collection集合

  1. 定义

    • Collection是单列集合, 用于存储单个元素
    • Collection是一个接口, 他的下面有多个子接口和实现类, 我们称之为Collection体系
  2. 分类

    • List 集合中的元素是有序的,可以存放重复元素
    • Queue 队列, 除优先级外, 保持先进先出的原则(基本不用)
    • Set 集合中的元素是无序的, 不能存放重复的元素
  3. 体系图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9jOAUvXn-1619488505726)(Collection集合体系图.jpg)]

  4. 常用方法

    • boolean add(E e) 添加元素
    • boolean remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话
    • void clear() 移除此 collection 中的所有元素
    • boolean contains(Object o) 判断集合中是否包含指定元素
    • boolean isEmpty() 判断集合中元素的个数是否为空
    • int size() 获取集合中元素的个数
  5. 案例演示

    public static void main(String[] args) {
      	//如果没有泛型,会报出警告,不影响运行
    	Collection<Student> collection = new ArrayList<>();
    	
    	Student student1 = new Student("小红", 18);
    	Student student2 = new Student("小明", 19);
    	
    	collection.add(student1);	//添加方法
    	collection.add(student2);
    	
    	//判断集合中是否包含某个元素
    	System.out.println(collection.contains(student1));//结果为 : true
    	
    	//判断集合中元素的个数是否为null
    	System.out.println(collection.isEmpty());//结果: false
    	
    	//获取集合中元素的个数
    	System.out.println(collection.size());//结果为 : 2
    	
    	//移除某个元素
    	System.out.println(collection.remove(student2));//结果:true
    	System.out.println(collection.size());//结果: 1
    	
    	//清空集合中的元素
    	collection.clear();
    	System.out.println(collection.size());//结果为0
    }
    
  6. 集合中所有带All的方法

    • boolean addAll(Collection c) 将指定 collection 中的所有元素都添加到此 collection 中
    • boolean removeAll(Collection c) 移除此 collection 中那些也包含在指定 collection 中的所有元素
    • boolean containsAll(Collection c) 如果此 collection 包含指定 collection 中的所有元素
    • boolean retainAll(Collection c) 仅保留此 collection 中那些也包含在指定 collection 的元素
    • 演示
    public static void main(String[] args) {
    	Collection<Student> collection = new ArrayList<>();
    	
    	Student student1 = new Student("小红", 18);
    	Student student2 = new Student("小明", 19);
    	
    	collection.add(student1);	//添加方法
    	collection.add(student2);
    	
    	Collection<Student> collection2 = new ArrayList<>();
    	
    	Student student3 = new Student("小辉", 18);
    	collection2.add(student1);
    	collection2.add(student3);
    	
    	//将collection2集合中的元素添加到collection集合中
    	collection.addAll(collection2);
    	System.out.println(collection.size());//结果: 4
    
    	//判断collection集合中是否包含collection2集合中的所有元素
    	boolean flg = collection.containsAll(collection2);
    	System.out.println(flg);//结果: true
    	
    	//仅在collection中保留两个集合中相同的元素
    	collection.retainAll(collection2);
    	System.out.println(collection.size());//结果: 3
    }
    

四. 迭代器

  1. 定义

    • 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
  2. 案例演示遍历集合

    public static void main(String[] args) {
    	Collection<Student> collection = new ArrayList<>();
    	
    	Student student1 = new Student("小红", 18);
    	Student student2 = new Student("小明", 19);
    	Student student3 = new Student("小辉", 18);
    	
    	collection.add(student1);	//添加方法
    	collection.add(student2);
    	collection.add(student3);
    	
    	//集合转数组进行遍历
    	Object[] obs= collection.toArray();
    	
    	for (int i = 0; i < obs.length; i++) {
    		System.out.println(obs[i]); //前提集合内的元素重写了toString()方法
    	}
    }
    
  3. 迭代器的遍历形式

    • 步骤
      • 获取迭代器
      • 调用hashNext()方法判断下一个元素是否存在
      • 调用next()方法获取元素
    • 演示
    public static void main(String[] args) {
    	Collection<Student> collection = new ArrayList<>();
    	
    	Student student1 = new Student("小红", 18);
    	Student student2 = new Student("小明", 19);
    	Student student3 = new Student("小辉", 18);
    	
    	collection.add(student1);	//添加方法
    	collection.add(student2);
    	collection.add(student3);
    	
    	//for循环的形式
    	for(Iterator<Student> it = collection.iterator();it.hasNext();){
    		Student student = it.next();
    		System.out.println(student);
    	}
    	
    	//while循环的形式
    	Iterator<Student> it = collection.iterator();
    	while(it.hasNext()){
    		Student student = it.next();
    		System.out.println(student);
    	}
    }
    
  4. 迭代器工作原理

    • Iterator是一个接口,规定了迭代器的基本使用, 集合的子类都实现了迭代器方法, 同时返回属于自己的迭代器对象
    • 迭代器相当于是集合的一个副本, 里面记录了集合的基本属性值.
    • 使用时,我们先调用hashNext方法判断是否有下一个元素,如果有则返回true,否则返回false
    • 然后调用next()方法,返回当前指针所在位置上的元素
  5. 修改集合导致的异常

    • 当我们使用迭代器遍历集合的时候,如果对集合进行了修改,下一次循环会报错
    • 原因: 集合会记录修改的次数, 如果迭代器发现集合副本和原集合修改次数不一样的话就会报错
    • 解决办法: 使用迭代器的删除方法
    • 演示
    public static void main(String[] args) {
    	Collection<Student> collection = new ArrayList<>();
    	
    	Student student1 = new Student("小红", 18);
    	Student student2 = new Student("小明", 19);
    	
    	collection.add(student1);	//添加方法
    	collection.add(student2);
    
    	//while循环的形式
    	Iterator<Student> it = collection.iterator();
    	while(it.hasNext()){
    		Student student = it.next();
    		//collection.remove(student);
             it.remove();
    	}
    }
    

五. List集合

  1. 定义
    • List集合是有序的,可以储存重复的数据
    • List集合通过记录元素在集合中的位置来准确的查找元素
  2. List集合体系
    • ArrayList 底层使用数组(线程不安全)
    • LinkedList 底层使用链表
    • Vector 底层使用数组(线程安全的,不推荐使用)

六. ArrayList集合

  1. 定义

    • 低层使用的是数组, 所以其特性非常接近于数组
    • 储存的元素是有序的,而且可以重复存储, 通过数组角标来查询更改元素,速度非常快
    • 由于每次增删都要改动数组中的角标,所有导致增删效率低下
  2. ArrayList的增删改查原理

    • ArrayList 集合初始化会有一个默认长度是10的数组, 内部还有一个记录当前元素个数的变量, 当储存的元素个数超过数组长度之后,容量就会扩充一半
    • 当我们去查询集合中的元素时, 需要提供给集合一个角标值, 然后通过这个角标值查找集合中的元素
    • 当我们去删除一个元素的时候, 集合就会根据角标删除这个元素,并且改动其他元素的位置,这就是导致增删缓慢的原因
    • 其实如果我们是连续往集合尾部插入数据的话, 速度其实是非常快的, 因为其他元素的位置不需要改动,但是如果我们插入数据的位置是数组的前面或者中间,速度就会有明显的降低
  3. 构造方法

    • ArrayList() 构造一个初始化容量为10的空列表
    • ArrayList(Collection<? exends E> e) 构造一个包含执行集合元素的列表
    • ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表
  4. 常用方法

    • boolean add(E e) 将指定的元素添加到此列表的尾部
    • void add(int index,E element) 将指定的元素插入此列表中的指定位置
    • boolean contains(Object o) 如果此列表中包含指定的元素,则返回true
    • E get(int index) 通过角标查找元素
    • int indexOf(Object o) 返回此列表中首次出现的指定元素的索引, 或如果没有则返回 -1
    • int lastIndexOf(Object o) 返回此列表中最后一次出现的指定元素的索引(从后先前查)没有返回-1
    • boolean remove(Object o) 移除此列表中首次出现的指定元素(如果存在)
    • E set(int index , E element) 用指定元素替代此列表中指定位置上的元素,返回原来的元素
    • int size() 返回此列表中的元素数
  5. 演示

    public static void main(String[] args) {
    	ArrayList<String> list = new ArrayList<>();
    	
    	//添加元素
    	list.add("小红");
    	list.add("小明");
    	//将元素添加到角标1上
    	list.add(1,"小辉");
    	
    	System.out.println(list.contains("小明"));//true
    	
    	//通过角标获取
    	String str = list.get(1);
    	System.out.println(str);//结果: 小辉
    	
    	//通过元素获取角标
    	System.out.println(list.indexOf("小明"));//结果 : 2
    	
    	//通过角标移除元素
    	System.out.println(list.remove(1));//结果: true
    	
    	//通过角标设置元素
    	System.out.println(list.set(1, "小李"));//小辉
    	
    }
    
  6. ArrayList集合的遍历

    • for 循环遍历, 基本上等同于数组
    • 演示
    public static void main(String[] args) {
    	ArrayList<String> list = new ArrayList<>();
    	
    	list.add("小红");
    	list.add("小明");
    	list.add("小辉");
    	
    	for (int i = 0; i < list.size(); i++) {
    		System.out.println(list.get(i));
    	}
    }
    
    • 迭代器 使用公用迭代器
    • 演示
    public static void main(String[] args) {
    	ArrayList<String> list = new ArrayList<>();
    	
    	list.add("小红");
    	list.add("小明");
    	list.add("小辉");
    	
    	Iterator<String> it = list.iterator();
    	while (it.hasNext()) {
    		String str = it.next();
    		System.out.println(str);
    	}
    }
    
    • 迭代器2 List集合的迭代器(ListIterator) 可以从后往前遍历
    • 演示
    public static void main(String[] args) {
    	ArrayList<String> list = new ArrayList<>();
    	
    	list.add("小红");
    	list.add("小明");
    	list.add("小辉");
    	
    	ListIterator<String> it = list.listIterator();
    	while (it.hasNext()) {
    		String str = it.next();
    		System.out.println(str);
    	}
    	
    	while(it.hasPrevious()){
    		String str = it.previous();
    		System.out.println(str);
    	}
    }
    
  7. 测试题

    • 去除集合中的重复字符串元素
    • 演示
    public static void main(String[] args) {
    	ArrayList list = new ArrayList();
    	list.add("a");
    	list.add("b");
    	list.add("b");
    	list.add("b");
    	list.add("c");
    	list.add("c");
    	list.add("c");
    	list.add("c");
        list.add("a");
    	
    	System.out.println(list);
    	ArrayList newList = getSingle(list);
    	System.out.println(newList);
    }
    

七. LinkedList集合

  1. 定义

    • 底层使用的是链表,就好像一条锁链
    • 这个集合中的每个元素都被封装到一个叫Node的内部类中, 然后记录上一个元素和下一个元素的地址,通过手拉手形成一个链条
    • 增删快, 查询慢
  2. 增删改查的原理

    • 当需要去查询LinkedList集合中的元素时,需要从最开始的元素查找起,然后一层一层往后找,直到找到该元素,这样的动作十分消耗性能
    • 当需要去删除元素的时候, 我们只需要将被删除元素两端的元素重新连接到一起,或者新增的时候将新元素和左右两边的元素连起来就可以了
  3. 构造方法

    • LinkedList() 构造一个空列表
    • LinkedList(Collection<? extends E> e) 构造一个包含指定collection中元素的列表
  4. 常用方法

    • E remove() 获取并移除此列表的头
    • E poll() 获取并移除此列表的头
    • E peek() 获取但不移除此列表的头
  5. 演示

    public static void main(String[] args) {
    	LinkedList<String> list = new LinkedList<>();
    	
    	list.add("小红");
    	list.add("小明");
    	list.add("小辉");
    	
    	System.out.println(list.remove());//结果: 小红
    	System.out.println(list.size());//结果:2
    	
    	System.out.println(list.poll());//结果: 小明
    	System.out.println(list.size());//结果:1
    	
    	System.out.println(list.peek());//结果: 小辉
    	System.out.println(list.size());//结果:1
    }
    

八. ArrayList, LinkedList 及Vector集合之间的区别

  1. 线程安全
    • Vector : 线程安全
    • ArrayList, LinkedList : 线程不安全
  2. 实现方式
    • LinkedList : 链表
    • ArrayList,Vector : 数组
  3. 扩容
    • ArrayList和Vector使用数组实现, 当数组长度不够,内部会创建一个更大的数组
    • LinkedList 不存在这方面的问题
  4. 速度
    • ArrayList 查改块, 增删慢
    • LinkedList 查改慢, 增删快

总结

  1. 集合

    集合是一个容器

    已经学过数组了, 数组也是容器,为什么今天还要学习集合呢?

    数组使用起来太麻烦了 : 长度无法改变, 没有办法添加和删除

    集合的长度动态的, 有增删改查的方法, 使用起来非常方便

  2. 集合的体系

    Collection : 单列集合 一个位置上存一个元素

    • List : 有序 可以存储重复元素
      • ArrayList
      • LinkedList
    • Set : 无序, 不能存储重复元素

    Map : 双列集合

  3. LIst集合的常用功能

    add(E) add(index,E) remove(index) remove(E) set(E) get(index)

    indexOf(E) lastIndexOf(E) clear() contains(E) size() isEmpty()

    addAll(Colleaction) removeAll(Colleaction) containsAll(Colleaction) retainAll(Colleaction)

  4. ArrayList

    ArrayList() ArrayList(capacity) ArrayList(Colleaction)

    底层数组, 需要扩容 , 增删效率低 查改效率高 ,线程不安全

  5. LinkedList

    ArrayList() ArrayList(Colleaction)

    底层链表 , 不需要扩容 , 增删效率高 查改效率低, 线程不安全

  6. 迭代器

    用于遍历集合

    有些集合是没有角标的的, 无法使用for循环来遍历

    工作原理: 一个指针不断的往下移动

    使用方法 : hasNext() next();

作业

  1. 第一个题

    • 需求: 定义一个swap()方法,传入集合和两个角标,将两个角标上的元素交换位置
  2. 第二题

    • 需求: 创建一个Student类,定义name和age属性,创建几个Student对象放入集合中,遍历集合,查找年龄最大的对象,并打印
  3. 第三题

    • 需求: 定义集合让集合中添加多个元素,然后将集合中的元素位置反转
  4. 第四题

    • 需求: 创建一个Student类,定义name和age属性, 创建几个对象存入集合中(有重复属性的对象),创建方法去除集合中的重复元素
  5. 扩展题

    • 第一题

      • 需求: 现在有16只球队, 科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚,日本,美国,中国,新西兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利. 将这16只球队存入到集合中,然后随机分成4组存入到4个集合中.遍历打印集合
    • 第二题

      • 需求: 创建一个Student类, 定义 姓名,年龄,班级,成绩 属性, 然后创建多个对象存入集合中, 求出所有学生的平均年龄和每个班级的平均成绩
      • Student类的属性如下所示
          private String name;
          private int age;
          private  int score;
          private String ClassNum;
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值