廖雪峰java教程学习笔记——集合

本文详细介绍了Java集合框架中的List、Map、Set和Queue,包括ArrayList、LinkedList、Map的实现原理、哈希冲突解决、TreeMap、PriorityQueue等,以及如何遍历和操作这些集合。此外,还讲解了 equals() 和 hashcode() 方法的重要性,以及使用Iterator和Collections工具类的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java的java.util包主要提供了三种类型的集合:List、Set、Map

Java集合的设计特点:

  1. 接口和实现类相分离,例如有序表的接口是List,具体的实现类有ArrayList、LinkedList等
  2. 支持泛型
  3. 访问集合总是通过迭代器

注意:避免使用历史遗留类和接口

有一小部分集合类是遗留类,不应该继续使用:

  1. Hashtable:一种线程安全的Map实现;
  2. Vector:一种线程安全的List实现;
  3. Stack:基于Vector实现的LIFO的栈。

还有一小部分接口是遗留接口,也不应该继续使用:

  1. Enumeration:已被Iterator取代。

List 有序列表

List<E>接口主要有以下方法:

在末尾添加一个元素:boolean add(E e)
在指定索引添加一个元素:boolean add(int index, E e)
删除指定索引的元素:E remove(int index)
删除某个元素:boolean remove(Object e)
获取指定索引的元素:E get(int index)
获取链表大小(包含元素的个数):int size()

常用的实现有:ArrayList和LinkedList

ArrayList

ArrayList内部由数组实现,增删元素时会自动将其余元素挪位置,加满时会自动创建一个更大的数组,将原数组的所有元素复制过去,取代旧数组。

LinkedList

LinkedList内部由链表实现。

创建List

方法一:创建空List,用add添加元素
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(3);

或用双括号:

List<Integer> list=new ArrayList<Integer>(){
   {
   
                        add(1);
                        add(2);
                        add(3);
                          }};
方法二:使用Arrays.asList()
//创建List
List<Integer> list=Arrays.asList(1, 2, 3);  //注意要用Integer
//创建元素为List的list
List<List<Integer>> list = Arrays.asList(Arrays.asList(1,2), Arrays.asList(3,4));

注意Arrays.asList()创建的List是一个只读对象,不能再用add操作了:

        List<Integer> list = List.of(12, 34, 56);
        list.add(999); // UnsupportedOperationException

asList 是 java.util.Arrays 类的一个方法

public static <T> List<T> asList(T... a) {
   
        return new ArrayList<>(a);
}

容易犯的错误:

        int[] array = {
   1,2,3};
        List myList = Arrays.asList(array);  //将array对象作为list元素了

因为asList的接口是泛型:List<T> asList(T...) ,int作为原始类型不属于Object,所以不能被作为泛类型参数。整个数组倒是一个Object,所以整个数组就用来取代T,所以得到了一个List<int[]>。正确的做法是传入一个Integer[],就能得到一个List<Integer>了。

方法三:从Stream中创建
@Test
public void givenStream_thenInitializeList(){
   
    List<String> list = Stream.of("foo", "bar")
      .collect(Collectors.toList());
		
    assertTrue(list.contains("foo"));
}
方法四:工厂方法 .of (Java 9)

Java 9+ 版本,可以用List.of()取代Arrays.asList()

遍历List

方法一:for循环 + get(i)
        for (int i=0; i<list.size(); i++) {
   
            String s = list.get(i);
            System.out.println(s);
        }

不推荐这种方法,因为只对ArrayList高效,对LinkedList很低效。

方法二:迭代器Iterator (推荐!)

迭代器:

        for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
   
            String s = it.next();
            System.out.println(s);
        }

简化版为:

		//自动使用迭代器
        for (String s : list) {
   
            System.out.println(s);
        }

不同的List类型,返回的Iterator对象实现也是不同的,但总是具有最高的访问效率。

Java的for each循环会自动使用Iterator遍历。实际上,只要实现了Iterable接口的集合类都可以直接用for each循环来遍历。

List转为Array

Integer[] array = list.toArray(new Integer[3]);
Integer[] array = list.toArray(new Integer[list.size()]);
Integer[] array = list.toArray(Integer[]::new);  //函数式写法

编写equals方法

List中contains()、indexOf()等方法使用equals()方法判断两个元素是否相等。

因此,对于自定义的类型,要想正确使用List的contains()、indexOf()这些方法,放入的实例必须正确覆写equals()方法,否则,放进去的实例查找不到。

public class Person {
   
    public String name;
    public int age;
}

public boolean equals(Object o) {
   
    if (o instanceof Person) {
   
        Person p = (Person) o;
        //引用字段用equals,基本类型字段用==
        return this.name.equals(p.name) && this.age == p.age;
    }
    return false;
}

但上面方法中若this.namenullequals()方法就会报错。一种解决方式是手动判断是否为null,但这显然太麻烦。一般使用Objects.equals()静态方法即可。

标准覆写equals()方法样例:

public boolean equals(Object o) {
   
    if (o instanceof Person) {
   
        Person p = (Person) o;  //安全向下转型
        return Objects.equals(this.name, p.name) && this.age == p.age;
    }
    return false;
}

Map 映射表

put(),get()分别用于添加、获取映射。

        Student s = new Student("Xiao Ming", 99);
        Map<String, Student> map = new HashMap<>();  //创建HashMap
        map.put("Xiao Ming", s); // 添加元素
        Student target = map.get("Xiao Ming"); // 查找元素

遍历Map,顺序是不确定的:

        //方法一:通过key遍历,keySet()相当于python中的keys()
        for (String key : map.keySet()) {
     
            Integer value = map.get(key);
            System.out.println(key + " = " + value);
        }
		//方法二:直接遍历key、value,entrySet()相当于python中的items()
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
   
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " = " + value);
        }

用List存储全量数据,用Map做缓存的例子:

class Students {
   
	List<Student> list;//定义了一个Student的List,可能十分巨大
	Map<String, Integer> cache;//定义了一个Map,缓存
廖雪峰 Java 教程 Java教程 Java快速入门 Java简介 安装JDK 第一个Java程序 Java代码助手 使用IDE 使用IDE练习插件 Java程序基础 Java程序基本结构 变量和数据类型 整数运算 浮点数运算 布尔运算 字符和字符串 数组类型 流程控制 输入和输出 if判断 switch多重选择 while循环 do while循环 for循环 break和continue 数组操作 遍历数组 数组排序 多维数组 命令行参数 面向对象编程 面向对象基础 方法 构造方法 方法重载 继承 多态 抽象类 接口 静态字段和静态方法 包 作用域 classpath和jar 模块 Java核心类 字符串和编码 StringBuilder StringJoiner 包装类型 JavaBean 枚举类 BigInteger BigDecimal 常用工具类 异常处理 Java的异常 捕获异常 抛出异常 自定义异常 使用断言 使用JDK Logging 使用Commons Logging 使用Log4j 使用SLF4J和Logback 反射 Class类 访问字段 调用方法 调用构造方法 获取继承关系 动态代理 注解 使用注解 定义注解 处理注解 泛型 什么是泛型 使用泛型 编写泛型 擦拭法 extends通配符 super通配符 泛型和反射 集合 Java集合简介 使用List 编写equals方法 使用Map 编写equals和hashCode 使用EnumMap 使用TreeMap 使用Properties 使用Set 使用Queue 使用PriorityQueue 使用Deque 使用Stack 使用Iterator 使用Collections IO File对象 InputStream OutputStream Filter模式 操作Zip 读取classpath资源 序列化 Reader Writer PrintStream和PrintWriter 日期与时间 基本概念 Date和Calendar LocalDateTime ZonedDateTime DateTimeFormatter Instant 最佳实践 单元测试 编写JUnit测试 使用Fixture 异常测试 条件测试 参数化测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值