Java的集合

一、集合概述

Java 集合是一套用于管理多个对象的工具类集合,提供了存储、检索、添加、删除、排序、遍历等高效操作,弥补了数组的局限性(数组长度固定、仅支持简单的元素访问)。

Java 集合框架主要分为两大体系,由顶层接口定义:

体系 核心接口 存储特点 典型实现类
单个元素存储 Collection 存储一组独立的元素 ListSetQueue
键值对存储 Map 存储键(Key)值(Value)映射 HashMapTreeMap

其中 Collection 是单个元素集合的根接口,Map 是键值对集合的根接口,二者无继承关系。

集合 vs 数组

特性 数组 集合
长度 固定,初始化时指定 动态可变
存储类型 基本类型 / 引用类型均可 仅引用类型(基本类型需包装)
操作方法 需手动实现(如扩容、排序) 内置丰富的操作方法
效率 访问速度快(直接索引) 部分集合(如 ArrayList)接近数组,部分(如 LinkedList)增删更快

二、Collection接口

Collection 是 Java 集合框架中所有单个元素集合的顶级接口 ,定义了一组通用的操作方法,其子接口(ListSetQueue)都继承并实现了这些方法,保证了集合操作的统一性。

Collection 作为根接口,为所有单列集合提供了通用的行为规范 ,它本身不能直接实例化,需通过其子接口的实现类(如 ArrayListHashSet)来使用。

Collection 接口定义了一系列通用方法,适用于所有单列集合,主要分为以下几类:

方法分类 核心方法 功能说明
元素添加 boolean add(E e) 向集合中添加一个元素,成功返回 true
boolean addAll(Collection<? extends E> c) 将另一个集合的所有元素添加到当前集合,成功返回 true
元素删除 boolean remove(Object o) 从集合中移除指定元素,成功返回 true
boolean removeAll(Collection<?> c) 移除当前集合中与指定集合共有的所有元素(求差集)
void clear() 清空集合中所有元素
元素查询 int size() 返回集合中元素的个数
boolean isEmpty() 判断集合是否为空(元素个数为 0)
boolean contains(Object o) 判断集合是否包含指定元素
boolean containsAll(Collection<?> c) 判断集合是否包含指定集合的所有元素
迭代遍历 Iterator<E> iterator() 返回迭代器(Iterator)对象,用于遍历集合元素
集合转换 Object[] toArray() 将集合转换为 Object 类型数组
<T> T[] toArray(T[] a) 将集合转换为指定类型的数组
其他 boolean retainAll(Collection<?> c) 保留当前集合中与指定集合共有的元素(求交集),其余元素移除

三、List接口

Collection 接口之后,List 是 Java 集合框架中单列集合的重要子接口,也是开发中最常用的集合类型之一。

1.List接口简介

ListCollection 接口的子接口,专门用于存储有序、可重复 的元素集合,其核心特征是为每个元素分配了索引 (从 0 开始),支持通过索引直接访问元素,这也是它与 Set 接口最核心的区别。

核心特性:

  • 有序性:元素的存储顺序与添加顺序一致,遍历结果与添加顺序相同。
  • 可重复性 :允许存储多个相同的元素(包括 null)。
  • 索引访问 :支持通过索引(int index)对元素进行增删改查,类似数组的访问方式。

List 接口在 Collection 通用方法的基础上,新增了一系列基于索引的操作方法,这是其核心特色:

方法签名 功能说明
E get(int index) 获取指定索引位置的元素
E set(int index, E element) 替换指定索引位置的元素,返回被替换的旧元素
void add(int index, E element) 在指定索引位置插入元素,后续元素后移
E remove(int index) 删除指定索引位置的元素,返回被删除的元素
int indexOf(Object o) 返回指定元素在集合中首次出现的索引,不存在则返回 -1
int lastIndexOf(Object o) 返回指定元素在集合中最后出现的索引,不存在则返回 -1
List<E> subList(int fromIndex, int toIndex) 获取从 fromIndex(包含)到 toIndex(不包含)的子集合

2.ArrayList集合

ArrayListList 接口最常用的实现类,底层基于动态扩容的数组实现,兼顾了数组的快速访问特性和集合的动态扩容能力。

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

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("赵六");
        // 获取集合中元素的个数
        System.out.println("集合长度:" + list.size());
        // 取出并打印指定位置的元素
        System.out.println("第2个元素为:" + list.get(1));
    }
}

3.LinkedList集合

LinkedListList 接口的另一个重要实现类,底层基于双向链表 实现,同时还实现了 Deque 接口(双端队列),支持队列、栈的操作。

核心特性

  • 底层结构:双向链表(每个节点包含前驱节点、后继节点引用,以及当前元素值)。
  • 扩容机制:无需提前分配容量,添加元素时只需创建新节点并修改链表引用,无扩容开销。
java 复制代码
import java.util.LinkedList;

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> linkedList = new LinkedList<>();
        
        // 添加元素
        linkedList.add("A");
        linkedList.addFirst("B"); // 添加到链表头部
        linkedList.addLast("C"); // 添加到链表尾部
        
        System.out.println(linkedList); // 输出:[B, A, C]
        
        // 访问首尾元素
        System.out.println(linkedList.getFirst()); // 输出:B
        System.out.println(linkedList.getLast()); // 输出:C
        
        // 删除首尾元素
        linkedList.removeFirst();
        System.out.println(linkedList); // 输出:[A, C]
    }
}

4.Iterator接口

Iterator(迭代器)是 Java 集合框架中用于遍历集合元素的标准接口 ,定义了遍历集合的通用方法,所有实现了 Collection 接口的集合(包括 List)都可通过 iterator() 方法获取迭代器对象。迭代器提供了一种统一的遍历方式,无需关心集合的底层实现(数组 / 链表),同时支持在遍历过程中安全删除元素。

核心方法:

方法签名 功能说明
boolean hasNext() 判断集合中是否还有未遍历的元素
E next() 获取下一个元素(调用前需先通过 hasNext() 判断,否则会抛出 NoSuchElementException
void remove() 删除最近一次通过 next() 获取的元素(可选操作,用于遍历中安全删除元素)
java 复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        
        // 获取迭代器
        Iterator<String> it = list.iterator();
        
        // 遍历元素
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
            
            // 遍历中删除指定元素(安全方式)
            if (s.equals("Python")) {
                it.remove();
            }
        }
        
        System.out.println(list); // 输出:[Java, C++]
    }
}

注意事项

  • 并发修改异常 :遍历过程中,若直接调用集合的 add()/remove() 方法(而非迭代器的 remove()),会触发 ConcurrentModificationException,因为迭代器会检测集合的修改次数是否与预期一致。
  • 迭代器单向遍历Iterator 只能从前往后遍历,不支持反向遍历(若需反向遍历,可使用 ListIteratorList 接口特有的迭代器)。

5.foreach循环

foreach 循环(增强 for 循环)是 JDK 5 引入的语法糖 ,底层基于 Iterator 实现,提供了更简洁的遍历语法,适用于仅读取元素的场景。

核心特点:

  • 语法简洁:无需手动获取迭代器,直接遍历集合元素。
  • 只读遍历 :不支持在遍历过程中修改集合(添加 / 删除元素),否则同样会抛出 ConcurrentModificationException
  • 适用范围 :可遍历所有实现了 Iterable 接口的集合(包括 ListSet),也可遍历数组。
java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ForeachDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        
        // foreach 循环遍历 List
        for (String s : list) {
            System.out.println(s);
        }
        
        // foreach 遍历数组(扩展)
        int[] arr = {1, 2, 3};
        for (int num : arr) {
            System.out.println(num);
        }
    }
}

四、Set接口

在 Java 集合框架中,SetCollection 接口的重要子接口,与 List 形成互补,专注于无序、不可重复的元素存储。

1.Set接口简介

SetCollection 接口的子接口,定义了无序、不可重复的单列集合规范,是处理唯一元素集合的核心接口。

核心特性:

  • 不可重复性 :集合中不允许存在重复元素(判断依据是 equals() 方法返回 falsehashCode() 返回值不同,二者结合保证元素唯一性)。
  • 无序性 :元素的存储顺序与添加顺序无关(底层基于哈希表 / 红黑树实现,并非按插入顺序保存),且无索引,无法通过索引访问元素。
  • 继承通用方法 :完全继承 Collection 接口的方法,无额外扩展方法(因为索引操作对无序集合无意义)。

2.HashSet集合

HashSetSet 接口最常用的实现类,底层基于 HashMap 实现(利用 HashMap 的键存储元素,值为固定的 PRESENT 对象),是处理唯一元素的首选集合。

java 复制代码
import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        
        // 添加元素(重复元素不会被存储)
        set.add("Java");
        set.add("Python");
        set.add("Java"); // 重复元素,添加失败
        
        System.out.println(set); // 输出:[Java, Python](顺序可能不同)
        
        // 删除元素
        set.remove("Python");
        System.out.println(set); // 输出:[Java]
        
        // 遍历(无索引,使用迭代器或 foreach)
        for (String s : set) {
            System.out.println(s);
        }
    }
}
java 复制代码
import java.util.*;

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

    //重写toString()方法
    public String toString() {
        return id + ":" + name;
    }
    //重写hashCode方法
    public int hashCode() {
        return id.hashCode();
    }
    // 重写equals方法
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (! (obj instanceof Student)) {
            return false;
        }
        Student stu = (Student) obj;
        boolean b = this.id.equals(stu.id);
        return b;
    }
}

public class Example09 {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        Student s1 = new Student("1001", "张三");
        Student s2 = new Student("1002", "李四");
        Student s3 = new Student("1002", "李四");
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        System.out.println(hs);
    }
}

注意事项:若自定义类作为 HashSet 的元素,必须重写 hashCode()equals() 方法,否则无法保证元素唯一性(默认使用 Object 类的方法,基于对象地址判断,会导致相同内容的对象被视为不同元素)。

3.TreeMap集合

TreeMapMap 接口的实现类,底层基于红黑树 实现,用于存储有序的键值对,键具有唯一性且可排序。

java 复制代码
import java.util.TreeMap;
import java.util.Map;

public class TreeMapDemo {
    public static void main(String[] args) {
        Map<Integer, String> treeMap = new TreeMap<>();
        
        // 添加键值对
        treeMap.put(3, "C");
        treeMap.put(1, "A");
        treeMap.put(2, "B");
        
        // 遍历(按键的自然顺序排序)
        for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        // 输出:1:A  2:B  3:C
    }
}

4.Properties集合

PropertiesHashtable<Object, Object> 的子类,属于 Map 接口的实现类,专门用于处理配置文件 (如 .properties 文件),键和值均为 String 类型。

核心方法:

方法签名 功能说明
String getProperty(String key) 根据键获取值,若键不存在返回 null
String getProperty(String key, String defaultValue) 根据键获取值,若键不存在返回默认值
Object setProperty(String key, String value) 设置键值对(等同于 put() 方法)
void load(InputStream inStream) 从字节输入流中读取 .properties 文件的内容到集合中
void store(OutputStream out, String comments) 将集合中的键值对写入字节输出流(保存为 .properties 文件)
java 复制代码
import java.util.*;

public class Example21 {
    public static void main(String[] args) {
        Properties p = new Properties(); // 创建Properties对象
        p.setProperty("BackgroundColor", "red");
        p.setProperty("FontSize", "14px");
        p.setProperty("Language", "chinese");
        Enumeration names = p.propertyNames(); // 获取所有属性名
        while (names.hasMoreElements()) {
            String key = (String) names.nextElement(); // 遍历所有属性名
            String value = p.getProperty(key); // 根据属性名获取属性值
            System.out.println(key + " = " + value); // 输出属性名和属性值
        }
    }
}

五、Map接口

在 Java 集合框架中,Map 是与 Collection 并列的顶级接口,专注于键值对(Key-Value) 的存储与操作,是开发中处理映射关系数据的核心工具。

1.Map接口简介

Map 是 Java 集合框架中存储键值对的顶级接口 ,定义了一组通过键(Key)访问值(Value)的规范,其核心是键的唯一性键与值的一一映射关系

核心特性:

  • 键值对存储:每个元素由一个键(Key)和一个值(Value)组成,键是唯一的,值可以重复。
  • 无序性(默认) :大部分实现类(如 HashMap)中,元素的存储顺序与添加顺序无关(LinkedHashMap 除外)。
  • 无索引:无法通过索引访问元素,只能通过键来获取对应的值。
  • 键值类型 :支持泛型,可指定键和值的类型(如 Map<String, Integer>),避免类型转换异常。

核心方法

Map 接口定义了操作键值对的通用方法,主要分为以下几类:

方法分类 核心方法 功能说明
元素添加 V put(K key, V value) 向集合中添加键值对,若键已存在,则替换对应的值并返回旧值;若键不存在,返回 null
元素添加 void putAll(Map<? extends K, ? extends V> m) 将另一个 Map 的所有键值对添加到当前 Map
元素删除 V remove(Object key) 根据键删除对应的键值对,返回被删除的值;若键不存在,返回 null
元素删除 void clear() 清空 Map 中所有键值对
元素查询 V get(Object key) 根据键获取对应的值;若键不存在,返回 null
元素查询 int size() 返回 Map 中键值对的个数
元素查询 boolean isEmpty() 判断 Map 是否为空(键值对个数为 0)
元素查询 boolean containsKey(Object key) 判断 Map 是否包含指定的键
元素查询 boolean containsValue(Object value) 判断 Map 是否包含指定的值
集合视图 Set<K> keySet() 返回所有键组成的 Set 集合(键的唯一性对应 Set 的特性)
集合视图 Collection<V> values() 返回所有值组成的 Collection 集合
集合视图 Set<Map.Entry<K, V>> entrySet() 返回所有键值对(Map.Entry 对象)组成的 Set 集合,用于遍历 Map

2.HashMap集合

HashMapMap 接口最常用的实现类,底层基于哈希表(数组 + 链表 / 红黑树) 实现,是处理键值对映射的首选集合。

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

public class HashMapDemo {
    public static void main(String[] args) {
        // 创建 HashMap,指定键为 String 类型,值为 Integer 类型
        Map<String, Integer> map = new HashMap<>();
        
        // 添加键值对
        map.put("Java", 90);
        map.put("Python", 85);
        map.put("Java", 95); // 键重复,替换值
        
        // 根据键获取值
        System.out.println(map.get("Java")); // 输出:95
        
        // 遍历方式1:遍历所有键,再通过键获取值
        Set<String> keys = map.keySet();
        for (String key : keys) {
            System.out.println(key + ":" + map.get(key));
        }
        
        // 遍历方式2:遍历键值对(推荐,效率更高)
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        
        // 删除键值对
        map.remove("Python");
        System.out.println(map); // 输出:{Java=95}
    }
}

注意事项

  • 若自定义类作为 HashMap 的键,必须重写 hashCode()equals() 方法,否则无法保证键的唯一性。
  • 避免使用可变对象作为键(如 ArrayList),否则对象内容修改后,哈希值会变化,导致无法正确获取对应的值。

3.TreeMap集合

TreeMapMap 接口的有序实现类,底层基于红黑树(自平衡的二叉查找树) 实现,专注于按键排序的键值对存储。

java 复制代码
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapDemo {
    public static void main(String[] args) {
        // 1. 自然排序(键为 Integer,默认按升序排列)
        Map<Integer, String> treeMap1 = new TreeMap<>();
        treeMap1.put(3, "C");
        treeMap1.put(1, "A");
        treeMap1.put(2, "B");
        System.out.println(treeMap1); // 输出:{1=A, 2=B, 3=C}
        
        // 2. 定制排序(键为 String,按字符串长度降序排列)
        Map<String, Integer> treeMap2 = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s2.length() - s1.length(); // 降序
            }
        });
        treeMap2.put("Java", 90);
        treeMap2.put("Python", 85);
        treeMap2.put("C", 95);
        System.out.println(treeMap2); // 输出:{Python=85, Java=90, C=95}
    }
}

4.Properties集合

PropertiesHashtable<Object, Object> 的子类,属于 Map 接口的特化实现类,专门用于处理配置文件(如 .properties 文件) ,键和值均为 String 类型。

java 复制代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo {
    public static void main(String[] args) throws IOException {
        // 1. 创建 Properties 集合
        Properties prop = new Properties();
        
        // 2. 设置键值对
        prop.setProperty("username", "admin");
        prop.setProperty("password", "123456");
        prop.setProperty("port", "8080");
        
        // 3. 写入到 .properties 配置文件
        prop.store(new FileOutputStream("config.properties"), "System Config");
        
        // 4. 从配置文件读取内容
        Properties prop2 = new Properties();
        prop2.load(new FileInputStream("config.properties"));
        
        // 5. 获取配置值
        System.out.println("用户名:" + prop2.getProperty("username")); // 输出:用户名:admin
        System.out.println("端口:" + prop2.getProperty("port", "80")); // 输出:端口:8080
    }
}

六、泛型

泛型是 Java 5 引入的核心特性之一,它解决了集合等容器类的类型安全问题,消除了大量的类型转换代码,提升了代码的可读性和可维护性。

1.泛型概述

定义:泛型(Generic)本质是参数化类型,即允许在定义类、接口、方法时,将类型作为参数来传递,使用时再指定具体的类型。就像方法的形参是值的占位符,泛型的类型参数是类型的占位符。

泛型的核心优势

  1. 编译时类型检查:编译器会在编译阶段检查类型是否匹配,避免运行时类型转换异常。
  2. 消除强制类型转换:使用时指定类型,取出元素时无需手动转换,代码更简洁。
  3. 代码复用:通过类型参数,可编写通用的类、方法,适配不同类型的需求。

泛型的本质:泛型是编译时的语法糖 ,JVM 在运行时并不识别泛型的类型参数(即类型擦除 ),编译后会将泛型类型擦除为原始类型(如 List<String> 擦除为 List),并在必要时插入类型转换代码。这意味着泛型仅在编译阶段起作用,目的是为了编译器的类型检查。

2.泛型类和泛型对象

泛型类是在类的定义中引入类型参数的类,语法格式为:

java 复制代码
修饰符 class 类名<类型参数列表> {
    // 类的成员变量、方法等可使用类型参数
}

类型参数:通常用单个大写字母表示,常用的约定:

  • E:Element(元素,用于集合)
  • T:Type(类型)
  • K:Key(键)
  • V:Value(值)
  • N:Number(数字)

自定义泛型类:

java 复制代码
// 定义泛型类,T 为类型参数
public class GenericClass<T> {
    // 成员变量使用类型参数
    private T data;

    // 构造方法使用类型参数
    public GenericClass(T data) {
        this.data = data;
    }

    // 方法的返回值和参数使用类型参数
    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

创建泛型类的对象时,需要指定具体的类型实参,语法格式为:

java 复制代码
类名<具体类型> 对象名 = new 类名<具体类型>();

创建泛型对象:

java 复制代码
public class GenericClassDemo {
    public static void main(String[] args) {
        // 指定类型为 String
        GenericClass<String> strObj = new GenericClass<>("Hello Generic");
        System.out.println(strObj.getData()); // 输出:Hello Generic

        // 指定类型为 Integer
        GenericClass<Integer> intObj = new GenericClass<>(123);
        System.out.println(intObj.getData()); // 输出:123
    }
}
注意事项
  1. 类型参数不能是基本数据类型 :只能使用引用数据类型(如 Integer 而非 intString 而非 char)。
  2. 泛型类的静态成员不能使用类型参数:静态成员属于类本身,而类型参数是对象级别的,在类加载时类型参数尚未指定。
  3. 不能创建类型参数的数组 :如 T[] arr = new T[10] 是不允许的,因为类型擦除后无法确定数组的具体类型。

3.泛型方法

泛型方法是指在方法的定义中引入类型参数的方法,它可以定义在普通类中,也可以定义在泛型类中,泛型方法的类型参数独立于类的类型参数

语法格式为:

java 复制代码
修饰符 <类型参数列表> 返回值类型 方法名(参数列表) {
    // 方法体
}
java 复制代码
public class GenericMethodDemo {
    // 泛型方法:交换数组中两个元素的位置
    public <T> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        GenericMethodDemo demo = new GenericMethodDemo();
        
        // 处理 String 数组
        String[] strArr = {"Java", "Python", "C++"};
        demo.swap(strArr, 0, 2);
        System.out.println(Arrays.toString(strArr)); // 输出:[C++, Python, Java]
        
        // 处理 Integer 数组
        Integer[] intArr = {1, 2, 3};
        demo.swap(intArr, 1, 2);
        System.out.println(Arrays.toString(intArr)); // 输出:[1, 3, 2]
    }
}

4.泛型接口

泛型接口是在接口的定义中引入类型参数的接口,语法和使用方式与泛型类类似。

泛型接口的定义语法格式为:

java 复制代码
修饰符 interface 接口名<类型参数列表> {
    // 抽象方法可使用类型参数
    返回值类型 方法名(参数列表);
}

实现泛型接口有两种方式:

  1. 实现类指定具体类型:实现接口时直接指定类型参数的具体类型,成为普通类。
  2. 实现类保留类型参数:实现接口时仍使用类型参数,成为泛型类。

方式 1:实现类指定具体类型

java 复制代码
// 实现类指定 T 为 String
public class StringProcessor implements GenericInterface<String> {
    @Override
    public String process(String data) {
        return data.toUpperCase(); // 将字符串转为大写
    }
}

// 测试
public class GenericInterfaceDemo1 {
    public static void main(String[] args) {
        GenericInterface<String> processor = new StringProcessor();
        System.out.println(processor.process("java")); // 输出:JAVA
    }
}

方式 2:实现类保留类型参数

java 复制代码
// 实现类保留类型参数 T,成为泛型类
public class GenericProcessor<T> implements GenericInterface<T> {
    @Override
    public T process(T data) {
        // 简单返回原数据
        return data;
    }
}

// 测试
public class GenericInterfaceDemo2 {
    public static void main(String[] args) {
        GenericInterface<Integer> intProcessor = new GenericProcessor<>();
        System.out.println(intProcessor.process(123)); // 输出:123
    }
}

5.类型通配符

类型通配符用于在使用泛型时,表示未知的类型 ,主要解决泛型类型不兼容的问题,常用的通配符有 ?? extends 上限? super 下限

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

public class BoundedWildcardSuper {
    // 向集合中添加整数
    public static void addIntegers(List<? super Integer> list) {
        list.add(1);
        list.add(2);
        // list.add(3.14); // 错误:Double 不是 Integer 的子类
    }

    public static void main(String[] args) {
        List<Object> objList = new ArrayList<>();
        addIntegers(objList);
        System.out.println(objList); // 输出:[1, 2]
        
        List<Number> numList = new ArrayList<>();
        addIntegers(numList);
        System.out.println(numList); // 输出:[1, 2]
    }
}
通配符的使用
通配符类型 含义 适用场景 操作限制
? 任意类型 仅读取数据 不能添加元素(除 null),获取为 Object
? extends T T 或 T 的子类 只读(获取) 不能添加元素(除 null)
? super T T 或 T 的父类 只写(添加) 获取元素为 Object 类型

七、JDK8新特性------Lambda表达式

Lambda 表达式是 JDK 8 引入的核心特性之一,它是函数式编程的重要体现,允许将一段代码(行为)作为参数传递给方法,简化了匿名内部类的编写,大幅提升了代码的简洁性和可读性。

Lambda 表达式本质是一个可传递的代码块,可以在需要时执行一次或多次。它的出现主要是为了解决传统匿名内部类代码冗余、语法繁琐的问题,尤其适用于函数式接口的实现。

Lambda 表达式的使用前提是函数式接口,这是理解 Lambda 的关键:

  • 定义 :只包含一个抽象方法的接口(可以包含默认方法、静态方法、私有方法)。
  • 标识 :可使用 @FunctionalInterface 注解标记(可选,但推荐使用,编译器会检查是否符合函数式接口规范)。

Java 内置的 RunnableComparatorConsumerSupplier 等都是函数式接口:

java 复制代码
// 自定义函数式接口
@FunctionalInterface
public interface MyFunctionalInterface {
    void doSomething(String str); // 唯一抽象方法
    
    // 允许包含默认方法
    default void defaultMethod() {
        System.out.println("默认方法");
    }
}
Lambda 的核心优势
  1. 代码简洁:替代冗长的匿名内部类,一行代码即可实现接口的抽象方法。
  2. 行为参数化:将代码作为参数传递,实现更灵活的编程逻辑。
  3. 提升可读性:聚焦业务逻辑,减少模板代码的干扰。
相关推荐
大学生资源网2 小时前
基于springboot的乡村信息化管理系统的研究与实现(源码+文档)
java·spring boot·后端
鹿角片ljp2 小时前
力扣 83: 删除排序链表中的重复元素(Java实现)
java·leetcode·链表
渣渣盟2 小时前
网络命令大全:轻松解决网络故障
开发语言·php
Mr Tang2 小时前
Docker日志查看和应用日志查看命令大全
java·开发语言
invicinble2 小时前
java处理数据合集
java·开发语言
电商API_180079052472 小时前
淘宝评论API技术解析与调用实战指南
开发语言·爬虫·信息可视化
Json_2 小时前
springboot框架对接物联网,配置TCP协议依赖,与设备通信,让TCP变的如此简单
java·后端·tcp/ip
百***07452 小时前
gpt-image-1.5国内API稳定接入全方案(含多模态实操)
开发语言·gpt·php
小草cys2 小时前
HarmonyOS Next调用高德api获取实时天气,api接口
开发语言·python·arkts·鸿蒙·harmony os