java List Set Map

  1. List :元素有序、允许重复、带数字索引。实现类:ArrayList、LinkedList、Vector
  2. Set :元素无序、不允许重复 、没有索引。实现类:HashSet
  3. Map :存储键值对 key=value;key 唯一不能重复;value 可重复。HashMap

遍历集合三种方式

scss 复制代码
//1.普通for循环:只适用于List(有索引)
for(int i=0;i<list.size();i++){
    System.out.println(list.get(i));
}

//2.增强for‑each(全部Collection都能用)
for(String s : list){
    System.out.println(s);
}

//3.Iterator迭代器(Set必须用这个,删除元素安全)
Iterator<String> it = set.iterator();
while(it.hasNext()){
    String s = it.next();
    System.out.println(s);
}

ArrayList

  • 底层:动态 Object 数组
  • 查询快(数组随机索引);中间增删慢,需要数组拷贝移位
  • 线程不安全;扩容:默认容量 10,扩容 1.5 倍
arduino 复制代码
        // 方式一:默认构造,初始容量为10
        List<String> list1 = new ArrayList<>();

        // 方式二:指定初始容量(已知数据规模时推荐,避免频繁扩容)
        List<String> list2 = new ArrayList<>(20);

        // 方式三:从已有集合创建
        List<String> list3 = new ArrayList<>(Arrays.asList("A", "B", "C"));
csharp 复制代码
List<String> list = new ArrayList<>();

// ===== 增 =====
list.add("Java");              // 尾部添加
list.add(0, "Hello");          // 指定位置插入
list.addAll(Arrays.asList("World", "!"));  // 批量添加

// ===== 删 =====
list.remove(0);                // 按索引删除
list.remove("Java");           // 按对象删除(只删除第一个匹配项)
list.removeIf(s -> s.length() < 3);  // 条件删除(Java 8+)
list.clear();                  // 清空列表

// ===== 改 =====
list.set(0, "Python");         // 修改指定位置元素

// ===== 查 =====
String item = list.get(0);     // 获取指定位置元素 O(1)
int size = list.size();        // 获取元素个数
boolean contains = list.contains("Python");  // 判断是否包含某元素
int index = list.indexOf("World");         // 查找元素首次出现的位置
csharp 复制代码
// 对于基本数据类型,add的时候会自动装包
List<Integer> list = new ArrayList<>();
//remove的时候,默认是索引,所以需要包装成Integer类型
list.remove(Integer.valueOf(2));

注意迭代器的遍历

vbnet 复制代码
        // 每次都是拿的新的迭代器,没有状态保存
        // while (list.iterator().hasNext()) {
        // System.out.println(list.iterator().next());
        // }

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

LinkedList

  • 底层双向链表
  • 查询慢,要顺着链表遍历;首尾增删速度快
  • 提供栈 / 队列方法:addFirst、addLast、removeFirst
  • 线程不安全
arduino 复制代码
        // 方式一:创建空链表
        LinkedList<String> list1 = new LinkedList<>();

        // 方式二:从已有集合创建
        LinkedList<String> list2 = new LinkedList<>(Arrays.asList("A", "B", "C"));
arduino 复制代码
LinkedList<String> list = new LinkedList<>();

        // ===== 增 =====
        list.add("Java"); // 尾部添加
        list.addFirst("Hello"); // 头部添加 O(1)
        list.addLast("World"); // 尾部添加 O(1)
        list.add(2, "Python"); // 指定位置插入(需先遍历定位,O(n))

        // ===== 删 =====
        list.remove(0); // 按索引删除
        list.remove("Java"); // 按对象删除(删除第一个匹配项)
        list.removeFirst(); // 删除头部 O(1)
        list.removeLast(); // 删除尾部 O(1)
        list.clear(); // 清空链表

        // ===== 改 =====
        list.set(0, "Kotlin"); // 修改指定位置元素(需先遍历定位,O(n))

        // ===== 查 =====
        String item = list.get(0); // 获取指定位置元素 O(n)
        String first = list.getFirst(); // 获取头部元素 O(1)
        String last = list.getLast(); // 获取尾部元素 O(1)
        int size = list.size(); // 获取元素个数
        boolean contains = list.contains("Kotlin"); // 判断是否包含某元素
        int index = list.indexOf("World"); // 查找元素首次出现的位置

作为队列(Queue)使用

arduino 复制代码
LinkedList<String> queue = new LinkedList<>();

// 入队(尾部添加)
queue.offer("Task1");
queue.offer("Task2");
queue.offer("Task3");

// 查看队首(不删除)
System.out.println("队首: " + queue.peek());  // Task1

// 出队(移除并返回队首)
while (!queue.isEmpty()) {
    System.out.println("处理: " + queue.poll());
}

作为栈(Stack)使用

arduino 复制代码
LinkedList<String> stack = new LinkedList<>();

// 压栈(头部添加)
stack.push("Data1");
stack.push("Data2");
stack.push("Data3");

// 弹栈(移除并返回头部)
while (!stack.isEmpty()) {
    System.out.println("弹出: " + stack.pop());
}

遍历方式

vbnet 复制代码
// 1. 增强 for 循环(最常用)
for (String s : list) {
    System.out.println(s);
}

// 2. 迭代器遍历(支持边遍历边安全删除)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String s = iterator.next();
    if (s.equals("Kotlin")) {
        iterator.remove();  // 安全删除
    }
}

// 3. ListIterator 双向遍历(LinkedList 特有优势)
ListIterator<String> listIterator = list.listIterator();
// 正向遍历
while (listIterator.hasNext()) {
    System.out.print(listIterator.next() + " ");
}
// 反向遍历
while (listIterator.hasPrevious()) {
    System.out.print(listIterator.previous() + " ");
}

Vector 不推荐使用

  • 底层数组;所有方法synchronized加锁,线程安全,性能慢,基本淘汰

Set集合 & hashCode/equals

Set:无序、元素不可重复,没有索引 。常用实现类:HashSet

csharp 复制代码
HashSet<String> set = new HashSet<>();
set.add("张三");
set.add("李四");
set.add("张三"); //重复元素,添加失败,不会报错
System.out.println(set); //[张三,李四],重复被去重
  1. Set没有get(index),没有普通for循环;只能用增强for、Iterator迭代器遍历

  2. HashSet底层:HashMap哈希表(数组+链表/红黑树)

  3. 去重规则:

    • 先比较 hashCode()哈希值;哈希不一样直接判定两个对象不同。
    • 哈希值相同,再用equals()做内容比较;equals返回true才判定为重复对象,拒绝存入。

⚠️自定义对象存入HashSet:必须重写 hashCode() 和 equals(),否则按内存地址判断,不会按业务属性去重。

示例学生实体:

java 复制代码
class Student{
    private int id;
    private String name;
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
    //必须重写这两个方法,HashSet才能按id+name去重
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id && Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

练习

csharp 复制代码
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;

class Hello {

    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("Java");
        set.add("Go");
        set.add("Rust");
        set.add("Java");
        for (String item : set) {
            System.out.println(item);
        }
        System.out.println("-----------------");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        HashSet<Student> set2 = new HashSet<>();
        set2.add(new Student("张三", 1001));
        set2.add(new Student("李四", 1002));
        set2.add(new Student("张三", 1001));
        for (Student item : set2) {
            System.out.println(item);
        }
        System.out.println("-----------------");
        Iterator<Student> iterator2 = set2.iterator();
        while (iterator2.hasNext()) {
            System.out.println(iterator2.next());
        }
    }
}

class Student {
    String name;
    int id;

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Student student = (Student) obj;
        return id == student.id && name.equals(student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}
// 小细节:`name.equals(student.name)`,如果 name 有可能为 null 会空指针;`Objects.equals(name, student.name)`更安全。

Map集合(HashMap核心)

Map存储 key‑value键值对

  • key:唯一不可重复;value允许重复

  • 一个key只能对应一个value;重复put同一个key,旧value会被覆盖

  • 底层HashMap:哈希表(数组+链表+红黑树),无序

Map常用API

scss 复制代码
V put(K key,V value)      //存入键值对,key重复覆盖旧值
V get(Object key)         //根据key获取value,找不到返回null
boolean containsKey(key) //判断key是否存在
remove(key)               //删除该key对应的键值对
keySet()                  //获取全部key的Set集合
entrySet()                //获取全部键值对对象 Set<Map.Entry<K,V>>
size()

HashMap三种遍历方式

arduino 复制代码
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

class Hello{
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"张三");
        map.put(2,"李四");
        map.put(3,"王五");

        //方式1:keySet 获取所有key,再get拿value
        Set<Integer> keySet = map.keySet();
        for(Integer key : keySet){
            System.out.println(key + " -> " + map.get(key));
        }

        //方式2:entrySet,拿键值对对象(性能最好,推荐)
        Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
        for(Map.Entry<Integer,String> entry : entrySet){
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }

        //方式3:lambda forEach(jdk8)
        map.forEach((k,v)->{
            System.out.println(k+":"+v);
        });
    }
}

重要面试点

  1. HashMap的key,自定义对象做key,同样必须重写hashCode()与equals() ,否则去重失效。
  2. HashMap线程不安全;并发环境用ConcurrentHashMap。
  3. 默认初始容量16,负载因子0.75;达到容量*0.75触发扩容,扩容为原来2倍。

📝练习任务

  1. 创建HashMap<String,Integer>;put存入:"张三"‑22,"李四"‑24,"王五"‑21;重复put一次"张三"‑99观察覆盖效果。
  2. 使用 keySet、entrySet、lambda forEach 三种方式全部遍历打印。
  3. 判断key="赵六"是否存在;删除key="李四",打印map。
arduino 复制代码
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

class Hello {

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三", 22);
        map.put("李四", 24);
        map.put("王五", 21);
        map.put("张三", 99);
        // 使用 keySet、entrySet、lambda forEach 三种方式全部遍历打印
        for (String key : map.keySet()) {
            System.out.println(key + " -> " + map.get(key));
        }
        System.out.println("-----------------");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " -> " + entry.getValue());
        }
        System.out.println("-----------------");
        map.forEach((key, value) -> System.out.println(key + " -> " + value));

        // 判断key="赵六"是否存在;删除key="李四",打印map。
        System.out.println("赵六是否存在:" + map.containsKey("赵六"));
        map.remove("李四");
        System.out.println("删除李四后:" + map);
    }
}
相关推荐
杨杨杨大侠1 小时前
聊几句就能让 AI 写代码,Spec 还有必要吗?
java·openai·ai编程
编程老船长1 小时前
模型中立——把大模型做成"可替换零件",而不是焊死在业务里
java·前端·后端
IT枫斗者枫哥1 小时前
MyBatis只查两次,为什么还会查到别家客户?
java·数据库
明月_清风1 小时前
Tomcat 到底是什么?一篇文章搞懂 Java Web 的 Tomcat
java·后端
xiaoqiMikko1 小时前
JVM 线上排查实战(三):grep BLOCKED 找不到的死锁,和 jstack 根本不报的死锁
java·jvm
用户3721574261351 小时前
如何使用 Java 从 PDF 中提取图片及获取图片信息
java
咕白m6251 小时前
如何在 Word 中创建可填充表单(Java 实现)
java
devpotato1 小时前
把 MySQL 索引讲透:从 B+ 树结构到线上索引治理
java·mysql
SL_staff1 小时前
JVS-Logic 实践:如何将‘需求→上线’从11天压缩至2小时?
java·后端·开源