Java 集合 示例

发布于:2025-07-16 ⋅ 阅读:(23) ⋅ 点赞:(0)

Collection

package com.example.demo1;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collection;

public class CollectionDemo {
    public static void main(String[] args) {
        // ======================================
        // 1. 初始化Collection集合(使用ArrayList实现)
        // ======================================
        Collection<String> fruits = new ArrayList<>();


        // ======================================
        // 2. 演示Collection常用方法
        // ======================================
        // boolean add(E e):添加元素
        fruits.add("苹果");
        fruits.add("香蕉");
        fruits.add("橙子");
        System.out.println("添加后集合:" + fruits);  // 输出:[苹果, 香蕉, 橙子]

        // boolean contains(Object o):判断是否存在
        System.out.println("是否包含香蕉:" + fruits.contains("香蕉"));  // 输出:true

        // int size():集合长度
        System.out.println("当前集合大小:" + fruits.size());  // 输出:3

        // boolean remove(Object o):移除指定元素
        System.out.println("移除苹果结果:" + fruits.remove("苹果"));  // 输出:true
        System.out.println("移除后集合:" + fruits);  // 输出:[香蕉, 橙子]

        // boolean isEmpty():判断是否为空
        System.out.println("集合是否为空:" + fruits.isEmpty());  // 输出:false

        // boolean removeIf(Predicate):根据条件移除(需要Java 8+)
        // 示例:移除所有包含"橙"字的元素
        boolean removed = fruits.removeIf(fruit -> fruit.contains("橙"));
        System.out.println("条件移除结果:" + removed);  // 输出:true
        System.out.println("条件移除后集合:" + fruits);  // 输出:[香蕉]

        // void clear():清空集合
        fruits.clear();
        System.out.println("清空后集合:" + fruits);  // 输出:[]


        // ======================================
        // 3. 重新填充数据用于遍历演示
        // ======================================
        fruits.add("葡萄");
        fruits.add("草莓");
        fruits.add("芒果");


        // ======================================
        // 4. 迭代器遍历(Iterator)
        // ======================================
        Iterator<String> iterator = fruits.iterator();
        System.out.println("\n迭代器遍历:");
        while (iterator.hasNext()) {  // 判断是否有下一个元素
            String fruit = iterator.next();  // 获取当前元素并移动指针
            System.out.print(fruit + " ");   // 输出:葡萄 草莓 芒果 
            
            // 示例:用迭代器删除元素(安全操作)
            if ("草莓".equals(fruit)) {
                iterator.remove();  // 删除当前指向的元素
            }
        }
        System.out.println("\n迭代器删除后集合:" + fruits);  // 输出:[葡萄, 芒果]


        // ======================================
        // 5. 增强for循环(for-each)
        // ======================================
        System.out.println("\n增强for循环遍历:");
        for (String fruit : fruits) {  // 自动遍历集合中每个元素
            System.out.print(fruit + " ");  // 输出:葡萄 芒果 
        }


        // ======================================
        // 6. Lambda表达式的使用(结合Collection的forEach)
        // ======================================
        System.out.println("\nLambda表达式遍历:");
        fruits.forEach(fruit -> {  // Lambda表达式替代匿名内部类
            System.out.print(fruit + " ");  // 输出:葡萄 芒果 
        });
        // 更简洁的Lambda写法(方法引用)
        // fruits.forEach(System.out::print);
    }
}

能使用 Lambda 表达式,需满足以下条件

1. 目标类型为函数式接口

Lambda 表达式只能用于函数式接口的上下文。函数式接口指的是仅包含一个抽象方法的接口。

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

Predicate<T> 被 @FunctionalInterface 注解标记,表明它是函数式接口,且只有一个抽象方法 test(T t)。所以,removeIf 方法的参数位置可使用 Lambda 表达式。

2. 参数类型兼容

Lambda 表达式的参数类型要和函数式接口中抽象方法的参数类型兼容。Predicate<String> 里 test 方法的参数类型为 String,因此 Lambda 表达式的参数类型也得是 String,像 fruit -> fruit.contains("橙") 中,fruit 就被推断为 String 类型。

3. 返回值类型匹配

Lambda 表达式的返回值类型要和函数式接口中抽象方法的返回值类型一致。Predicate<String> 里 test 方法的返回值类型是 boolean,所以 fruit -> fruit.contains("橙") 的返回值也得是 boolean 类型,contains 方法恰好返回 boolean 类型的值,满足要求。

不用Lambda 表达式的写法

// ... 已有代码 ...
// boolean removeIf(Predicate):根据条件移除(需要Java 8+)
// 示例:移除所有包含"橙"字的元素
boolean removed = fruits.removeIf(new java.util.function.Predicate<String>() {
    @Override
    public boolean test(String fruit) {
        return fruit.contains("橙");
    }
});
System.out.println("条件移除结果:" + removed);  // 输出:true
System.out.println("条件移除后集合:" + fruits);  // 输出:[香蕉]
// ... 已有代码 ...

LinkedList

package com.example.demo1;

import java.util.LinkedList;  // 需要导入LinkedList类

public class a {
    public static void main(String[] args) {
        // 创建一个存储String类型的LinkedList
        LinkedList<String> fruits = new LinkedList<>();

        // 1. 演示 addFirst 和 addLast
        fruits.addFirst("Apple");  // 列表变为: [Apple]
        fruits.addLast("Banana");  // 列表变为: [Apple, Banana]
        fruits.addFirst("Grape");  // 列表变为: [Grape, Apple, Banana]
        System.out.println("添加后列表: " + fruits);  // 输出: [Grape, Apple, Banana]

        // 2. 演示 getFirst 和 getLast
        String first = fruits.getFirst();  // 获取第一个元素
        String last = fruits.getLast();    // 获取最后一个元素
        System.out.println("第一个元素: " + first);  // 输出: Grape
        System.out.println("最后一个元素: " + last);   // 输出: Banana

        // 3. 演示 removeFirst 和 removeLast
        String removedFirst = fruits.removeFirst();  // 删除并返回第一个元素(Grape)
        String removedLast = fruits.removeLast();    // 删除并返回最后一个元素(Banana)
        System.out.println("被删除的第一个元素: " + removedFirst);  // 输出: Grape
        System.out.println("被删除的最后一个元素: " + removedLast);   // 输出: Banana
        System.out.println("删除后的列表: " + fruits);  // 输出: [Apple]
    }
}

泛型能避免强制类型转换

package com.example.demo1;

import java.util.ArrayList;

public class a {
    public static void main(String[] args) {
        // 示例1:不使用泛型(原始类型)
        ArrayList rawList = new ArrayList();  // 未指定泛型类型
        rawList.add("Java泛型示例");  // 添加String类型元素
        // 取出元素时需要强制类型转换(因为编译器不知道元素具体类型)
        String rawStr = (String) rawList.get(0);
        System.out.println("非泛型方式获取:" + rawStr);

        // 示例2:使用泛型(指定<String>类型)
        ArrayList<String> genericList = new ArrayList<>();  // 指定泛型类型为String
        genericList.add("Java泛型优势");  // 编译器会检查只能添加String类型
        // 取出元素时无需强制转换(编译器已知是String类型)
        String genericStr = genericList.get(0);
        System.out.println("泛型方式获取:" + genericStr);
    }
}

TreeSet 基本使用与遍历

import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        // 1. 基本使用:TreeSet 自动排序且去重(元素需可比较)
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Grape");
        fruits.add("Apple"); // 重复元素会被自动去重

        System.out.println("TreeSet 内容(自然排序): " + fruits); // 输出: [Apple, Banana, Grape]

        // 2. 遍历方式
        // 方式1:迭代器
        System.out.println("迭代器遍历:");
        Iterator<String> iterator = fruits.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " "); // Apple Banana Grape 
        }

        // 方式2:增强 for 循环
        System.out.println("\n增强 for 遍历:");
        for (String fruit : fruits) {
            System.out.print(fruit + " "); // Apple Banana Grape 
        }

        // 方式3:forEach + Lambda
        System.out.println("\nLambda 遍历:");
        fruits.forEach(fruit -> System.out.print(fruit + " ")); // Apple Banana Grape 
    }
}

自然排序(Comparable 接口)

若要让自定义对象存入 TreeSet,需实现 Comparable 接口并重写 compareTo 方法(定义自然排序规则)。

// ...(接上面的 TreeSetDemo 类,添加内部类)
static class Student implements Comparable<Student> {
    String name;
    int age;

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

    // 重写 compareTo:按年龄升序排序(自然排序规则)
    @Override
    public int compareTo(Student other) {
        // 核心逻辑:当前对象(this)与参数对象(other)比较
        // 返回负数:this < other → 排在前面
        // 返回0:相等 → 不重复存储
        // 返回正数:this > other → 排在后面
        return this.age - other.age; 
        // 若年龄相同,可追加其他字段比较(例如姓名):
        // return this.age != other.age ? this.age - other.age : this.name.compareTo(other.name);
    }

    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + "}";
    }
}
// ...(在 main 方法中添加测试代码)
// 3. 自然排序测试(Student 需实现 Comparable)
TreeSet<Student> students = new TreeSet<>();
students.add(new Student("张三", 20));
students.add(new Student("李四", 18));
students.add(new Student("王五", 22));
students.add(new Student("赵六", 18)); // 年龄与李四相同,若 compareTo 未处理姓名会被去重

System.out.println("\n\n学生集合(自然排序): " + students); 
// 输出: [Student{name='李四', age=18}, Student{name='张三', age=20}, Student{name='王五', age=22}]
// 注:赵六因年龄与李四相同(compareTo 返回0)会被视为重复,未被存储

比较器排序(Comparator 接口)

若不想修改原有类(或需要自定义排序规则),可在创建 TreeSet 时传入 Comparator 比较器(覆盖自然排序规则)。

// ...(在 main 方法中添加测试代码)
// 4. 比较器排序(Comparator 覆盖自然排序)
TreeSet<Student> studentsByComparator = new TreeSet<>((s1, s2) -> {
    // 自定义规则:姓名长度降序(若长度相同,按年龄升序)
    int lenCompare = s2.name.length() - s1.name.length(); 
    return lenCompare != 0 ? lenCompare : s1.age - s2.age;
});

studentsByComparator.add(new Student("张三", 20));    // 姓名长度2
studentsByComparator.add(new Student("李四四", 18));  // 姓名长度3
studentsByComparator.add(new Student("王五五五", 22));// 姓名长度4
studentsByComparator.add(new Student("赵六", 18));    // 姓名长度2

System.out.println("学生集合(比较器排序): " + studentsByComparator); 
// 输出: [Student{name='王五五五', age=22}, Student{name='李四四', age=18}, Student{name='张三', age=20}, Student{name='赵六', age=18}]


网站公告

今日签到

点亮在社区的每一天
去签到