【从零开始java学习|第二十二篇】集合进阶之collection

目录

概述

1、根接口:Collection

2、两大家族

3、记忆口诀

[一、单列集合顶层接口 ------Collection](#一、单列集合顶层接口 ——Collection)

核心方法

[定义Collection coll= new ArrayList<>(); 怎么理解?](#定义Collection coll= new ArrayList<>(); 怎么理解?)

[二、Collection 的遍历方式](#二、Collection 的遍历方式)

[1. 迭代器遍历(Iterator)](#1. 迭代器遍历(Iterator))

​编辑

[2. 增强 for 遍历(for-each)](#2. 增强 for 遍历(for-each))

[3. Lambda 表达式遍历](#3. Lambda 表达式遍历)

[三、List 中常见的方法和五种遍历方式](#三、List 中常见的方法和五种遍历方式)

常见方法

五种遍历方式

[1. 迭代器遍历(同 Collection)](#1. 迭代器遍历(同 Collection))

[2. 增强 for 遍历(同 Collection)](#2. 增强 for 遍历(同 Collection))

[3. Lambda 表达式遍历(同 Collection)](#3. Lambda 表达式遍历(同 Collection))

[4. 普通 for 循环(利用索引)](#4. 普通 for 循环(利用索引))

[5. ListIterator 遍历(可双向遍历)](#5. ListIterator 遍历(可双向遍历))


概述

这张图是 Java 集合框架(Java Collections Framework)的"家谱"速览,用一句话就能背下来:

Collection 是根;List 和 Set 是两大家族;每个家族下面再分"谁有序、谁重复、谁带索引"。


1、根接口:Collection
  • 所有单列集合(一次只装一个元素)的共同祖先。

  • 定义了最通用的方法:add / remove / contains / size ...


2、两大家族
家族 特点(图中红字) 常见实现类 底层结构与使用场景
List 有序、可重复、有索引 ArrayList 数组,查询快、增删慢
LinkedList 双向链表,增删快、查询慢
Vector 老式线程安全数组(已过时)
Set 无序、不重复、无索引 HashSet 哈希表,去重首选,最快
LinkedHashSet 哈希表+链表,保留插入顺序
TreeSet 红黑树,自动排序(升序/自定义)

3、记忆口诀

List 系列:"有序可重复,带索引,像数组"

Set 系列:"无序不重复,无索引,像数学集合"

想保插入顺序 → 用 LinkedHashSet

想自动排序 → 用 TreeSet

只想去重最快 → 用 HashSet

把图旋转 90° 就是一条线:
Collection → List|Set → 具体实现类,先选家族(List/Set),再选特性(是否排序/是否线程安全/是否频繁增删),最后挑实现类即可。

一、单列集合顶层接口 ------Collection

java.util.Collection 是 Java 单列集合的顶层接口,它定义了所有单列集合(如 ListSet)通用的操作方法,是整个单列集合体系的基础。

核心方法

  • 添加元素boolean add(E e),向集合中添加元素,成功返回 true
  • 删除元素boolean remove(Object o),删除集合中指定的元素,成功返回 truevoid clear(),清空集合中的所有元素。
  • 判断元素boolean contains(Object o),判断集合中是否包含指定元素;boolean isEmpty(),判断集合是否为空。
  • 获取长度int size(),获取集合中元素的个数。
  • 转数组Object[] toArray(),将集合转换为数组。

定义Collection<Student>coll= new ArrayList<>(); 怎么理解?

这行代码:

复制代码
Collection<Student> coll = new ArrayList<>();

= 面向接口编程的"标准姿势",一句话拆解:

  1. 左边 Collection<Student>

    把变量声明成接口类型 (而不是具体类),以后想换 LinkedListHashSetTreeSet...只需改右边,调用者代码不动

  2. 右边 new ArrayList<>()

    真正创建的是ArrayList 实现类 对象,但向上转型为接口类型,只暴露 Collection 接口定义的功能(add/remove/contains/size...)。

  3. 泛型 <Student>

    告诉编译器:这个集合里只能放 Student 对象 ,放错类型直接报错,取出时无需强转

  4. 好处

    • 解耦:调用代码只依赖接口,不依赖具体实现。

    • 灵活:随时替换实现类,性能/特性需求变化零入侵。

    • 可读:一眼看出"这是存 Student 的集合",类型安全。

"左边接口,右边实现;接口变量,实现对象。"

更详细的说:

一、把变量声明成接口类型(而不是具体类)

  1. 先回忆两种写法

    复制代码
    ArrayList<Student>  list1 = new ArrayList<>();  // 左边是具体类
    Collection<Student> list2 = new ArrayList<>();  // 左边是接口
  2. 区别就像"遥控器"

    • 左边是遥控器外形(变量类型)。

    • 右边是真实机器(真正 new 出来的对象)。

    ArrayList 遥控器 → 上面 20 多个 ArrayList 特有按钮(如 ensureCapacity)都能按。

    Collection 遥控器 → 只有 10 个通用按钮(add/remove/contains/size...),看不到 ArrayList 特有按钮

  3. 为什么要"少按钮"

    以后你想把机器换成 LinkedListHashSet

    复制代码
    Collection<Student> list2 = new LinkedList<>(); // 遥控器外形不变

    后面所有代码(list2.add / list2.contains)一句不用改 ,因为它们只用到 Collection 那 10 个通用按钮。

    这就叫"面向接口编程 "------变量类型尽量用高层接口,代码更通用、更灵活


二、向上转型为接口类型(只暴露 Collection 功能)

  1. 向上转型(Up-casting)

    把子类对象当成父类型/接口类型来引用,不需要强制转换,Java 自动完成:

    复制代码
    ArrayList<>  子类对象  →  Collection<> 父接口变量
  2. 暴露范围

    转型后,编译器只让你调用 Collection 接口里有的方法 ,ArrayList 自己的特有方法(如 ensureCapacity)被"隐藏"了,防止误用,也降低耦合。


三、泛型是什么意思

  1. 没有泛型时(Java 5 以前)

    复制代码
    List list = new ArrayList();  // 任何 Object 都能放
    list.add("abc");
    list.add(123);                // 编译通过
    String s = (String) list.get(1); // 运行期 ClassCastException!
  2. 加入泛型后

    复制代码
    Collection<Student> coll = new ArrayList<>();

    编译阶段就告诉编译器:"这个集合里只能放 Student 对象"。

    复制代码
    coll.add("abc");  // 直接红线报错,连运行机会都不给

四、取出时无需强转

继续上面的例子:

  1. 有泛型

    复制代码
    Collection<Student> coll = new ArrayList<>();
    coll.add(new Student("张三", 23));
    Student stu = coll.iterator().next();  // 直接拿到 Student 类型
  2. 没有泛型

    复制代码
    Collection coll = new ArrayList();
    coll.add(new Student("张三", 23));
    Student stu = (Student) coll.iterator().next(); // 必须强转,否则编译错误

泛型在编译期自动插入隐式强转 ,所以你写代码时省掉了 (Student),既简洁又安全。

二、Collection 的遍历方式

1. 迭代器遍历(Iterator)

迭代器是专门用于遍历集合的工具,通过 Collectioniterator() 方法获取迭代器对象。

复制代码
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class IteratorDemo {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        collection.add("Java");
        collection.add("Python");
        collection.add("C++");

        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()) { // 判断是否有下一个元素
            String element = iterator.next(); // 获取下一个元素
            System.out.println(element);
        }
    }
}

2. 增强 for 遍历(for-each)

增强 for 循环是一种简化的遍历方式,内部基于迭代器实现,适用于遍历集合或数组。

复制代码
import java.util.ArrayList;
import java.util.Collection;

public class ForEachDemo {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        collection.add("Java");
        collection.add("Python");
        collection.add("C++");

        for (String element : collection) {
            System.out.println(element);
        }
    }
}

3. Lambda 表达式遍历

Java 8 及以上版本支持通过 Lambda 表达式结合 forEach() 方法遍历集合,代码更加简洁。

复制代码
import java.util.ArrayList;
import java.util.Collection;

public class LambdaDemo {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        collection.add("Java");
        collection.add("Python");
        collection.add("C++");

        collection.forEach(element -> System.out.println(element));
    }
}

三、List 中常见的方法和五种遍历方式

ListCollection 的子接口,它的元素有序、可重复、有索引 ,除了继承 Collection 的方法外,还新增了许多基于索引操作的方法。

常见方法

  • 添加元素void add(int index, E element),在指定索引处添加元素;boolean addAll(int index, Collection<? extends E> c),在指定索引处添加另一个集合中的所有元素。
  • 获取元素E get(int index),获取指定索引处的元素。
  • 修改元素E set(int index, E element),修改指定索引处的元素,返回被修改的旧元素。
  • 删除元素E remove(int index),删除指定索引处的元素,返回被删除的元素。
  • 查找索引int indexOf(Object o),返回指定元素在集合中第一次出现的索引;int lastIndexOf(Object o),返回指定元素在集合中最后一次出现的索引。
  • 子列表List<E> subList(int fromIndex, int toIndex),获取从 fromIndex(包含)到 toIndex(不包含)的子列表。

五种遍历方式

1. 迭代器遍历(同 Collection)
复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListIteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }
    }
}
2. 增强 for 遍历(同 Collection)
复制代码
import java.util.ArrayList;
import java.util.List;

public class ListForEachDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        for (String element : list) {
            System.out.println(element);
        }
    }
}
3. Lambda 表达式遍历(同 Collection)
复制代码
import java.util.ArrayList;
import java.util.List;

public class ListLambdaDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        list.forEach(element -> System.out.println(element));
    }
}
4. 普通 for 循环(利用索引)

由于 List 有索引,可通过普通 for 循环结合 get(index) 方法遍历。

复制代码
import java.util.ArrayList;
import java.util.List;

public class ListForDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        for (int i = 0; i < list.size(); i++) {
            String element = list.get(i);
            System.out.println(element);
        }
    }
}
5. ListIterator 遍历(可双向遍历)

ListIteratorIterator 的子接口,专门用于 List,支持向前和向后遍历,还能在遍历过程中修改集合。

复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListListIteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        ListIterator<String> listIterator = list.listIterator();
        // 向前遍历
        while (listIterator.hasNext()) {
            String element = listIterator.next();
            System.out.println(element);
        }

        // 向后遍历
        while (listIterator.hasPrevious()) {
            String element = listIterator.previous();
            System.out.println(element);
        }
    }
}

通过对 CollectionList 的学习,能更灵活地操作和遍历集合,满足不同场景下的数据处理需求,为后续学习 Set 等其他集合类型打下基础。

如果我的内容对你有帮助,请点赞,评论,收藏。接下来我将继续更新相关内容!

相关推荐
锥栗3 小时前
【Redis】【缓存】理解缓存三大问题:缓存穿透、缓存击穿与缓存雪崩及解决方案
java·后端·面试
9号达人3 小时前
泛型+函数式:让策略模式不再是复制粘贴地狱
java·后端·面试
captain3763 小时前
Java线性表
java·开发语言
tuokuac3 小时前
Java String类中的lastIndexOf方法的应用场景
java·开发语言
weixin_379880923 小时前
.Net Core WebApi集成Swagger
java·服务器·.netcore
@逆风微笑代码狗3 小时前
147.《手写实现 Promise.all 与 Promise.race》
java
_dindong3 小时前
基础算法:滑动窗口
数据结构·学习·算法·leetcode·力扣
ss2733 小时前
手写MyBatis第102弹:MapperBuilder与MapperAnnotationBuilder的双重解析机制深度剖析
java·开发语言·mybatis
星光一影4 小时前
Java版旅游系统/文旅系统/旅游助手/旅游攻略/公众号/小程序/app全套源码
java·小程序·开源软件·旅游·源代码管理