Java学习九—常用包(类)之java.util包

一、关于java.util包

1.1简介

java.util​ 包是Java标准类库中的一个非常重要的组成部分,它提供了一系列对程序开发非常有用的类和接口。这个包主要包含集合框架、日期时间类、事件模型、随机数生成器以及其他实用工具类。

24c6ea75-6c61-4368-8734-6ce8aeec8626

1.2常用类及接口

  1. 集合框架 - 集合框架是java.util​包中最重要的部分之一,它提供了一系列的数据结构和算法,帮助开发者存储和操作数据集合。

    • Collection​ - 集合框架的根接口,代表一组对象,这些对象称为元素。
    • List​ - 有序集合,每个元素都有其在集合中的特定位置。
    • Set​ - 不允许重复元素的集合。
    • Map​ - 键值对的集合,也称为字典或哈希表。
    • ArrayList​ - 实现了List​接口的动态数组。
    • LinkedList​ - 实现了List​接口的双向链表。
    • HashSet​ - 实现了Set​接口的哈希表集合。
    • LinkedHashSet​ - 继承自HashSet​,维护元素插入顺序的集合。
    • TreeSet​ - 实现了Set​接口的基于红黑树的集合,元素按自然顺序或自定义顺序排序。
    • HashMap​ - 实现了Map​接口的哈希表。
    • LinkedHashMap​ - 继承自HashMap​,维护元素插入顺序或访问顺序的映射。
    • TreeMap​ - 实现了Map​接口的基于红黑树的映射,键按自然顺序或自定义顺序排序。
  2. 日期时间类 - 提供了操作日期和时间的类。

    • Date​ - 表示特定的瞬间,精确到毫秒。
    • Calendar​ - 可以用于日期的计算,比如添加或减少天数、获取星期等。
    • TimeZone​ - 表示时区。
    • Locale​ - 表示特定的语言、国家和区域的设置。
  3. 事件模型 - 用于处理事件和监听器模式。

    • EventObject​ - 所有事件的超类。
    • EventListener​ - 所有事件监听器接口的标记接口。
    • EventSource​ - 能够生成事件的对象。
  4. 随机数生成器 - 提供随机数生成的功能。

    • Random​ - 基于线性同余生成器的随机数生成器。
    • java.security.SecureRandom​ - 提供更安全的随机数生成。
  5. 其他实用工具类 - 提供了一系列静态方法,用于执行各种任务。

    • Arrays​ - 提供静态方法来操作数组,如排序、搜索等。
    • Collections​ - 提供静态方法来操作集合,如排序、搜索等。
    • Objects​ - 提供静态方法来操作对象,如空安全的比较、计算哈希码等。
    • Timer​ - 可以调度任务在将来的某个时间点执行。
    • UUID​ - 用于生成UUID(通用唯一标识符)。

image

1.3时间

1.3.1Date类

简介

java.util.Date​ 类在Java中用于表示特定的瞬间,精确到毫秒。

image-20230626142849752

构造方法

Date类提供了多个构造方法,其中比较常用的有:

  • Date(): 创建一个表示当前日期和时间的Date对象。
  • Date(long date): 根据指定的毫秒数创建一个Date对象,该毫秒数表示自1970年1月1日00:00:00 GMT以来的毫秒数。

方法
  • getTime(): 返回自1970年1月1日00:00:00 GMT以来的毫秒数。
  • toString(): 将Date对象转换为String类型。
  • before(Date when): 比较两个日期,如果当前日期早于参数日期,则返回true。
  • after(Date when): 比较两个日期,如果当前日期晚于参数日期,则返回true。

示例
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // 创建表示当前日期和时间的Date对象
        Date currentDate = new Date();
        System.out.println("当前日期和时间:" + currentDate);

        // 创建一个指定日期和时间的Date对象
        Date specificDate = new Date(1630454400000L); // 对应2022年9月2日12:00:00
        System.out.println("指定日期和时间:" + specificDate);

        // 判断日期先后
        if (currentDate.after(specificDate)) {
            System.out.println("当前日期晚于指定日期");
        } else {
            System.out.println("当前日期早于指定日期");
        }
    }
}

1.3.2TimeZone类

简介

在Java中,TimeZone类用于表示时区信息,并提供了对时区进行操作的方法。它可以帮助我们在处理日期和时间时,将时间转换为特定时区下的时间,并进行时区之间的转换。

构造方法

TimeZone类是一个抽象类,不能直接实例化,但它提供了一些静态方法来获取TimeZone对象:

  • getTimeZone(String ID): 返回指定ID对应的TimeZone对象,例如:“GMT+08:00”。
  • getDefault(): 返回默认的TimeZone对象,通常是系统默认的时区。

方法

TimeZone类提供了一些常用的方法,包括但不限于:

  • getDisplayName(): 返回时区的名称。
  • getID(): 返回时区的ID。
  • getOffset(long date): 返回指定日期的偏移量,单位为毫秒。
  • inDaylightTime(Date date): 判断指定日期是否在夏令时时段内。
  • getAvailableIDs(): 返回所有可用的时区ID数组。

示例
import java.util.Date;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        // 获取默认的时区
        TimeZone defaultTimeZone = TimeZone.getDefault();
        System.out.println("默认时区:" + defaultTimeZone.getDisplayName());

        // 获取指定ID的时区
        TimeZone gmt8TimeZone = TimeZone.getTimeZone("GMT+08:00");
        System.out.println("GMT+08:00时区:" + gmt8TimeZone.getDisplayName());

        // 进行时区转换
        Date currentDate = new Date();
        System.out.println("当前日期和时间:" + currentDate);
        System.out.println("当前日期和时间在GMT+08:00时区:" + formatDateInTimeZone(currentDate, gmt8TimeZone));
    }

    // 将日期转换为指定时区下的日期
    private static Date formatDateInTimeZone(Date date, TimeZone timeZone) {
        long timeInUTC = date.getTime() - timeZone.getRawOffset();
        return new Date(timeInUTC);
    }
}

1.4集合框架

集合框架 - 集合框架是java.util​包中最重要的部分之一,它提供了一系列的数据结构和算法,帮助开发者存储和操作数据集合。

  • Collection​ - 集合框架的根接口,代表一组对象,这些对象称为元素。
  • List​ - 有序集合,每个元素都有其在集合中的特定位置。
  • Set​ - 不允许重复元素的集合。
  • Map​ - 键值对的集合,也称为字典或哈希表。
  • ArrayList​ - 实现了List​接口的动态数组。
  • LinkedList​ - 实现了List​接口的双向链表。
  • HashSet​ - 实现了Set​接口的哈希表集合。
  • LinkedHashSet​ - 继承自HashSet​,维护元素插入顺序的集合。
  • TreeSet​ - 实现了Set​接口的基于红黑树的集合,元素按自然顺序或自定义顺序排序。
  • HashMap​ - 实现了Map​接口的哈希表。
  • LinkedHashMap​ - 继承自HashMap​,维护元素插入顺序或访问顺序的映射。
  • TreeMap​ - 实现了Map​接口的基于红黑树的映射,键按自然顺序或自定义顺序排序。

在之前章节有详细介绍,这里不再赘述

image

1.5接口

1.5.1Comparator

简介

java.util.Comparator​ 接口是一个用于定义对象比较规则的接口。它允许开发者自定义对象比较逻辑,这在排序集合或者对对象进行排序操作时非常有用。Comparator​ 接口提供了一种灵活的比较机制,使得可以对任何对象进行排序,而不仅仅是实现了特定比较方法的对象。

方法
  • reversed(): 返回与当前比较器相反的比较器(逆序排列)。

  • thenComparing(): 返回一个复合比较器,用于对两个对象进行多重比较。

  • nullsFirst(): 返回一个可将null元素排在非null元素之前的比较器。

  • nullsLast(): 返回一个可将null元素排在非null元素之后的比较器。

  • compare(T o1, T o2) - 比较两个对象 o1​ 和 o2​。返回值是一个整数,它表示第一个参数相对于第二个参数是小于、等于还是大于:

    如果 o1​ 小于 o2​,返回负整数;

    如果 o1​ 等于 o2​,返回零;

    如果 o1​ 大于 o2​,返回正整数。

示例
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Student {
    private int id;
    private String name;

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

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

public class Main {
    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "Alice"));
        studentList.add(new Student(2, "Bob"));
        studentList.add(new Student(3, "Charlie"));

        // 使用Comparator进行排序
        Collections.sort(studentList, Comparator.comparing(Student::getName));
  
        // 输出排序后的结果
        for (Student student : studentList) {
            System.out.println("ID: " + student.getId() + ", Name: " + student.getName());
        }
    }
}

在这个示例中,首先定义了一个Student类,然后创建了一个包含Student对象的列表studentList。接着,我们使用Comparator.comparing方法根据学生姓名对列表进行排序,最终输出排序后的结果。

1.5.2Iterator

简介

在Java中,Iterator接口提供了一种用于遍历集合元素的统一方式。通过实现Iterator接口,我们可以对集合中的元素进行迭代访问,而不需要了解集合的具体实现方式。

方法
  • boolean hasNext(): 如果仍有元素可以迭代,则返回true,否则返回false。
  • E next(): 返回迭代的下一个元素。
  • void remove(): 从迭代器指向的集合中移除迭代器最后返回的元素(可选操作)。

示例
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        // 获取Iterator对象并进行迭代
        Iterator<String> iterator = names.iterator();
        while (iterator.hasNext()) {
            String name = iterator.next();
            System.out.println(name);
        }
    }
}

在这个示例中,首先创建了一个包含字符串元素的ArrayList names。然后,我们通过调用names的iterator()方法获得了一个Iterator对象,并使用while循环和next()方法对集合进行迭代访问,最终输出了每个元素的值。这种方式能够适用于任何实现了Iterable接口的集合类,如List、Set等。

1.5.3EventListener

简介

在Java中,EventListener接口是用于实现事件监听器的接口,用于处理各种类型的事件。通过实现EventListener接口,可以创建自定义的事件监听器,用于监听和响应特定类型的事件。

方法

EventListener​ 接口本身不定义任何方法,但是它有很多子接口,这些子接口定义了事件处理方法。例如:

  • ActionListener​:用于处理动作事件,如按钮点击。
  • ChangeListener​:用于监听 ChangeEvent​,当事件源的状态发生变化时触发。
  • MouseListener​:用于处理鼠标事件,如鼠标点击、移动等。
  • MouseMotionListener​:用于处理鼠标移动和拖动事件。
  • KeyListener​:用于处理键盘事件,如按键和释放。

示例
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class MyMouseListener implements MouseListener {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Mouse Clicked at: (" + e.getX() + ", " + e.getY() + ")");
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // 实现鼠标按下时的处理逻辑
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // 实现鼠标释放时的处理逻辑
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // 实现鼠标进入组件时的处理逻辑
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // 实现鼠标退出组件时的处理逻辑
    }
}

在这个示例中,创建了一个名为MyMouseListener的类,实现了MouseListener接口,该接口定义了处理鼠标事件的方法。我们重写了MouseListener接口中的几个方法,比如mouseClicked,在该方法中实现了鼠标点击事件发生时的逻辑。通过这种方式,我们可以自定义事件监听器来响应特定的事件。

1.6工具类

1.6.1UUID类

简介

java.util.UUID​ 类是用于生成通用唯一标识符(UUID)的工具类。UUID是一种标准化的32位字符格式,用于在分布式系统中唯一标识信息。UUID的设计目的是在所有计算机和系统上都能生成高度唯一的标识符,即使在不同的时间和空间中也是如此。

构造方法

UUID类提供了两种构造方法:

  1. UUID(long mostSignificantBits, long leastSignificantBits): 使用指定的最高有效位和最低有效位创建一个UUID对象。
  2. UUID(String name): 根据指定的字符串名称创建一个UUID对象。该字符串必须遵循UUID的标准格式,如 “550e8400-e29b-41d4-a716-446655440000”。
  3. UUID() - 生成一个随机生成的UUID。
UUID randomUUID = new UUID();

方法
  • static UUID randomUUID(): 静态方法,用于生成一个随机的UUID。
  • String toString(): 将UUID转换为字符串表示形式。
  • int hashCode(): 返回此UUID的哈希码值。
  • boolean equals(Object obj): 比较两个UUID对象是否相等。

示例
import java.util.UUID;

public class Main {
    public static void main(String[] args) {
        // 生成一个随机的UUID
        UUID uuid = UUID.randomUUID();

        // 将UUID转换为字符串表示形式
        String uuidString = uuid.toString();

        System.out.println("Random UUID: " + uuidString);
    }
}

在这个示例中,通过调用UUID.randomUUID()​方法生成一个随机的UUID对象,然后通过调用toString()​方法将其转换为字符串表示形式,并最终输出到控制台上。这样我们就可以生成一个唯一的标识符,用于在系统中标识对象或实体。

1.6.2Random类

简介

java.util.Random​ 类是Java标准库中提供的一个随机数生成器。它用于生成伪随机数流,这些随机数在足够长的时间内看起来是随机的,但实际上是可以重现的,因为它们是由一个初始种子值(seed)确定的。

image

构造方法
  1. Random(): 创建一个新的随机数生成器。
  2. Random(long seed): 使用指定的种子创建一个新的随机数生成器。使用相同的种子创建的Random对象将生成相同的随机数序列。

方法
  • int nextInt(): 返回一个随机的int值。
  • int nextInt(int bound): 返回一个大于等于0且小于bound的随机int值。
  • double nextDouble(): 返回一个随机的double值。
  • void nextBytes(byte[] bytes): 生成随机字节并将其放入提供的byte数组中。
  • boolean nextBoolean(): 返回一个随机的boolean值。

示例
import java.util.Random;

public class RandomExample {
    public static void main(String[] args) {
        // 使用默认构造方法创建Random对象
        Random random = new Random();

        // 生成一个随机整数
        int randomInt = random.nextInt();
        System.out.println("Random integer: " + randomInt);

        // 生成一个0到99之间的随机整数
        int randomIntWithinRange = random.nextInt(100);
        System.out.println("Random integer within range (0-99): " + randomIntWithinRange);

        // 生成一个随机double值
        double randomDouble = random.nextDouble();
        System.out.println("Random double: " + randomDouble);

        // 生成一个随机float值
        float randomFloat = random.nextFloat();
        System.out.println("Random float: " + randomFloat);

        // 生成一个随机long值
        long randomLong = random.nextLong();
        System.out.println("Random long: " + randomLong);

        // 生成一个随机boolean值
        boolean randomBoolean = random.nextBoolean();
        System.out.println("Random boolean (true or false): " + randomBoolean);

        // 使用自定义种子值创建Random对象
        Random randomWithSeed = new Random(123456L);

        // 再次生成随机整数,由于种子值相同,结果也将相同
        int sameRandomInt = randomWithSeed.nextInt();
        System.out.println("Same random integer with seed 123456: " + sameRandomInt);

        // 生成一个随机高斯分布值
        double randomGaussian = random.nextGaussian();
        System.out.println("Random Gaussian (normal distribution) value: " + randomGaussian);
    }
}

在这个示例中,首先创建了一个默认的 Random​ 对象,并使用它来生成不同类型的随机数。 接着,我们创建了一个带有自定义种子值的 Random​ 对象,并展示了如何通过指定种子值来重现相同的随机数序列。 最后,我们打印了生成的随机数,展示了 Random​ 类的各种用途。

1.6.3Scanner类

简介

在Java中,Scanner类是用于读取用户输入的一个方便的类,它可以从标准输入流(如键盘输入)、文件或字符串中获取输入数据。Scanner类提供了多种方法来解析基本数据类型和字符串。

image

构造方法
  1. Scanner(InputStream source): 通过指定输入流创建一个Scanner对象,通常用于从标准输入流(System.in)读取用户输入。
  2. Scanner(File source): 通过指定文件创建一个Scanner对象,用于从文件中读取数据。
  3. Scanner(String source): 通过指定字符串创建一个Scanner对象,用于从字符串中读取数据。

方法
  • int nextInt(): 读取下一个输入项并将其解释为int类型。
  • double nextDouble(): 读取下一个输入项并将其解释为double类型。
  • String nextLine(): 读取下一行输入。
  • boolean hasNext(): 检查是否还有输入项可读。
  • void close(): 关闭Scanner对象。

示例
import java.util.Scanner;

public class ScannerExample {
    public static void main(String[] args) {
        // 创建Scanner实例,使用System.in作为输入源
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入一个整数:");
        int integer = scanner.nextInt();
        System.out.println("您输入的整数是:" + integer);

        System.out.println("请输入一个浮点数:");
        double doubleValue = scanner.nextDouble();
        System.out.println("您输入的浮点数是:" + doubleValue);

        System.out.println("请输入一个布尔值(true/false):");
        boolean booleanValue = scanner.nextBoolean();
        System.out.println("您输入的布尔值是:" + booleanValue);

        System.out.println("请输入一个字符串:");
        String string = scanner.nextLine();
        System.out.println("您输入的字符串是:" + string);

        // 关闭Scanner实例
        scanner.close();
    }
}

在这个示例中,首先创建了一个 Scanner​ 实例,它默认使用 System.in​ 作为输入源。 接着,我们使用 nextInt()​、nextDouble()​、nextBoolean()​ 和 nextLine()​ 方法从用户那里读取不同类型的输入,并打印出来。 最后,我们调用 close()​ 方法关闭 Scanner​ 实例,释放与它关联的资源。

1.7java.util.concurrent包

1.7.1简介

java.util.concurrent 包提供了在并发编程中使用的工具类和框架。它包含了一系列用于处理并发任务的实用工具,使得在多线程环境中编写高效、安全的代码变得更加简单。

以下是 java.util.concurrent 包中一些常用的类和接口:

  1. Executor 框架:包括 Executor、ExecutorService 和 ScheduledExecutorService 接口,以及 Executors 工厂类。这些类允许你实现异步执行任务和控制执行过程。
  2. 线程安全集合:java.util.concurrent 包中提供了一系列线程安全的集合类,如 ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet 等。这些集合类能够在多线程环境中安全地进行读写操作,避免了传统集合类在并发情况下可能出现的线程安全问题。
  3. 同步器和锁:该包中还包含了一些同步器和锁的实现,如 ReentrantLock、ReadWriteLock、Condition 等,它们提供了更灵活的锁机制,能够满足不同的并发控制需求。
  4. 并发工具类:java.util.concurrent 包还提供了一些并发编程中常用的工具类,比如 CountDownLatch、CyclicBarrier、Semaphore 等。这些工具类可以帮助协调多个线程之间的执行顺序和资源的访问。

总的来说,java.util.concurrent 包为 Java 程序员提供了丰富的并发编程工具,帮助开发者更加轻松地处理多线程编程中的挑战,提高了并发程序的性能和可靠性。通过合理地利用这些工具和框架,可以写出高效、可靠的并发程序。

image

1.7.2CompletableFuture类

简介

在Java中,CompletableFuture类提供了一种异步编程的方式,可以用于实现异步操作和构建复杂的异步流水线。它是Java 8引入的一个重要特性,用于简化并发编程。

java.util.concurrent 包中的 CompletableFuture 类是 Java 8 引入的一个类,用于支持异步编程和构建异步操作链。CompletableFuture 提供了一种简洁而强大的方式来处理异步任务的结果,以及对多个异步任务进行组合、串联和并发控制。

以下是 CompletableFuture 类的一些主要特点和用法:

  1. 异步操作:CompletableFuture 可以表示一个异步计算的结果,通过 CompletableFuture 的方法可以注册回调函数,在异步任务执行完成后自动触发回调函数处理结果。
  2. 组合操作:CompletableFuture 支持对多个 CompletableFuture 进行组合操作,包括 thenCombine、thenCompose、thenApplyAsync 等方法,可以串联多个异步任务,形成复杂的异步操作链。
  3. 异常处理:CompletableFuture 允许你通过 exceptionally 或 handle 方法来处理异步任务中产生的异常,使得异常处理变得更加灵活。
  4. 并发控制:CompletableFuture 提供了一些方法来实现并发控制,比如 allOf、anyOf 等,能够控制多个 CompletableFuture 的执行顺序和并发度。
  5. 超时处理:CompletableFuture 支持设置超时时间,并在超时时执行特定的操作,避免任务长时间阻塞。

使用 CompletableFuture 可以简化异步编程的复杂性,让开发者能够更加方便地处理异步任务的结果和操作。通过链式调用和组合不同的 CompletableFuture 对象,可以构建出复杂的异步任务流水线,实现高效的并发编程。

总的来说,CompletableFuture 是 Java 中处理异步编程的重要工具,它提供了丰富的方法和功能,使得异步任务的管理和处理变得更加简单和高效。

构造方法

CompletableFuture类有多个静态工厂方法来创建CompletableFuture对象,其中最常用的包括:

  1. static CompletableFuture<Void> runAsync(Runnable runnable): 异步执行指定的Runnable任务,并返回一个CompletableFuture对象。
  2. static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier): 异步执行指定的Supplier任务,并返回一个CompletableFuture对象,该任务产生一个结果。

方法
  • CompletableFuture<T> thenApply(Function<? super T,? extends U> fn): 当前CompletableFuture计算完成时,对其结果执行给定的函数。
  • CompletableFuture<T> thenCompose(Function<? super T,? extends CompletionStage<U>> fn): 当前CompletableFuture计算完成时,对其结果执行给定的函数,该函数返回另一个CompletableFuture。
  • CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn): 当当前CompletableFuture计算完成或者抛出异常时,执行给定的函数。
  • static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs): 等待所有的CompletableFuture对象执行完毕。

示例
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建一个CompletableFuture对象,异步执行一个简单的任务
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Async task running in the background...");
            try {
                Thread.sleep(2000); // 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Async task completed.");
        });

        // 等待异步任务执行完毕
        future.get(); // 这里会阻塞直到任务完成

        System.out.println("Main thread continues to run...");
    }
}

在这个示例中,首先使用CompletableFuture.runAsync()​方法创建了一个CompletableFuture对象,异步执行一个简单的任务。然后使用get()​方法等待异步任务执行完毕。在主线程中,我们打印了一条消息表明主线程继续执行。这样我们就可以利用CompletableFuture类方便地实现异步编程。

1.8java.util.stream​包

1.8.1简介

java.util.stream​ 包是 Java 8 引入的用于支持流式处理(Stream API)的包。该包提供了一组类和接口,用于对集合数据进行函数式操作,以实现更简洁、可读性更强的代码。

以下是 java.util.stream​ 包中一些常用的类和接口:

  1. StreamStream​ 接口代表一个元素序列,可以支持各种操作来处理这个序列,如过滤、映射、归约等。
  2. CollectorsCollectors​ 类包含了一系列静态工厂方法,用于生成常见的收集器实例,例如将流元素收集到列表、集合、映射等数据结构中。
  3. IntStream, LongStream, DoubleStream:这些接口分别表示原始类型的流,提供了针对基本数据类型的特定操作。
  4. ParallelStreamParallelStream​ 类支持并行流操作,可以加速处理大量数据的操作。

通过使用 java.util.stream​ 包中提供的类和接口,开发者可以利用流式处理来简化集合数据的操作、提高代码的可读性,并且能够更方便地进行并行处理以提升性能。这些功能使得 Java 编程变得更加灵活和强大。

1.8.2Collectors类

简介

Collectors​ 类是 Java 中 java.util.stream​ 包中的一个工具类,提供了一系列静态工厂方法,用于生成常见的收集器实例,以便在流式处理中对元素进行汇总和归约操作。

通过 Collectors​ 类,可以方便地将流中的元素收集到不同类型的数据结构中,比如集合(List、Set)、映射(Map)、字符串(joining)、统计信息(summarizingInt、summarizingDouble 等)等。这些收集器可以帮助简化代码,并支持并行处理以提高性能。

构造方法

在 Java 中,Collectors​ 类是一个工具类,它提供了一系列静态工厂方法来创建不同类型的收集器。因此,Collectors​ 类并没有公开的构造方法。相反,它提供了诸如 toList()​、toSet()​、toMap()​ 等静态方法,用于创建对应的收集器实例。

这些静态方法返回的是 Collector​ 接口的实例,Collector​ 接口定义了用于执行归约操作的方式,并可用于对输入的元素进行汇总。Collector​ 接口中有几个重要的方法,包括 supplier()​、accumulator()​、combiner()​ 和 finisher()​,它们定义了收集器的行为和属性。

因此,我们通常不需要直接构造 Collectors​ 类的实例,而是通过调用其提供的静态工厂方法来获取特定类型的收集器。这样可以更方便地对流中的元素进行汇总和归约操作。

方法

一些常用的 Collectors​ 方法包括:

  • toList(): 将流中的元素收集到一个 List 中。
  • toSet(): 将流中的元素收集到一个 Set 中。
  • toMap(keyMapper, valueMapper): 将流中的元素根据 keyMapper 和 valueMapper 转换为 Map。
  • joining(): 将流中的元素连接成一个字符串。
  • groupingBy(classifier): 根据分类函数对流中的元素进行分组。
  • summarizingInt(), summarizingDouble(), summarizingLong(): 用于统计流中元素的汇总信息,如 count、sum、min、max、average 等。

  1. 将流中的元素收集到一个 List 中:
List<String> words = Arrays.asList("apple", "banana", "orange", "grape");
List<String> collectedList = words.stream()
                                .collect(Collectors.toList());
System.out.println(collectedList);
  1. 将流中的元素连接成一个字符串:
List<String> words = Arrays.asList("apple", "banana", "orange", "grape");
String concatenatedString = words.stream()
                                .collect(Collectors.joining(", "));
System.out.println(concatenatedString);
  1. 根据字符串长度将元素分组:
List<String> words = Arrays.asList("apple", "banana", "orange", "grape");
Map<Integer, List<String>> groupedByLength = words.stream()
                                                .collect(Collectors.groupingBy(String::length));
System.out.println(groupedByLength);
  1. 计算元素的数量、总和、最小值、最大值和平均值:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
IntSummaryStatistics stats = numbers.stream()
                                    .collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("Count: " + stats.getCount());
System.out.println("Sum: " + stats.getSum());
System.out.println("Min: " + stats.getMin());
System.out.println("Max: " + stats.getMax());
System.out.println("Average: " + stats.getAverage());

这些示例展示了如何使用 Collectors​ 类中的一些常见方法来对流进行汇总操作。您可以根据具体的需求选择合适的收集器,并结合流操作来实现各种数据处理功能。

示例
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        // 创建一个包含一些整数的List
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 使用Collectors.toList()方法将Stream中的元素收集到List中
        List<Integer> evenNumbers = numbers.stream()
                .filter(num -> num % 2 == 0)
                .collect(Collectors.toList());
        System.out.println("Even numbers: " + evenNumbers);

        // 使用Collectors.toSet()方法将Stream中的元素收集到Set中
        Set<Integer> oddNumbers = numbers.stream()
                .filter(num -> num % 2 != 0)
                .collect(Collectors.toSet());
        System.out.println("Odd numbers: " + oddNumbers);

        // 使用Collectors.toMap()方法将Stream中的元素收集到Map中
        Map<Integer, String> numberMap = numbers.stream()
                .collect(Collectors.toMap(
                        num -> num,
                        num -> "Number: " + num
                ));
        System.out.println("Number map: " + numberMap);
    }
}

在这个示例中,首先创建了一个包含一些整数的List。然后使用Stream API对这个List进行操作,并利用Collectors​类的方法将Stream中的元素收集到不同的数据结构中,包括List、Set和Map。最后我们打印出了收集到的结果。

1.8.3Stream类

简介

在 Java 中,Stream 是 Java 8 引入的一个全新的抽象概念,它提供了一种高效且功能强大的数据处理方式。Stream 可以让你以一种声明式的方式处理集合数据,这种方式更加简洁、灵活,并且可以充分利用多核处理器的优势。

简单来说,Stream 提供了一种对集合进行批量操作的高级抽象,它可以让你通过一系列的操作(如过滤、映射、排序、归约等)来处理集合中的元素,而无需写显式的循环。

构造方法

从集合创建

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> streamFromList = list.stream(); // 从List创建Stream
Stream<String> parallelStreamFromList = list.parallelStream(); // 从List创建并行Stream

从数组创建

String[] array = {"a", "b", "c"};
Stream<String> streamFromArray = Arrays.stream(array); // 从数组创建Stream

使用Stream.of()

Stream<String> streamOfElements = Stream.of("a", "b", "c"); // 使用Stream.of()创建Stream

使用Stream.iterate()

Stream<Integer> streamIterate = Stream.iterate(0, n -> n + 2).limit(5); // 使用Stream.iterate()创建Stream

使用Stream.generate()

Stream<Double> streamGenerate = Stream.generate(Math::random).limit(3); // 使用Stream.generate()创建Stream

方法

Stream 类提供了丰富的方法来支持对集合数据的高级操作,这些方法可以分为中间操作和终端操作两种类型。中间操作用于构建 Stream 流水线,而终端操作则触发实际的处理过程并产生结果。以下是一些常用的 Stream 方法:

中间操作:

  1. filter(Predicate) :根据给定的条件过滤元素。
  2. map(Function) :将元素按照指定规则转换。
  3. flatMap(Function) :将流中的每个元素都转换成另一个流,然后把所有流连接成一个流。
  4. distinct() :去除流中重复的元素。
  5. sorted() :对流进行排序。
  6. limit(long maxSize) :截断流,使其最多只包含指定数量的元素。
  7. skip(long n) :跳过指定数量的元素,返回剩余的元素。

终端操作:

  1. forEach(Consumer) :对流中的每个元素执行指定操作。
  2. collect(Collector) :将流中的元素累积成一个结果容器,如 List、Map 等。
  3. reduce(BinaryOperator) :用指定的二元运算符对流中的元素进行归约操作,得到一个最终结果。
  4. count() :返回流中元素的总个数。
  5. anyMatch(Predicate) :检查流中是否至少有一个元素满足给定条件。
  6. allMatch(Predicate) :检查流中是否所有元素都满足给定条件。
  7. noneMatch(Predicate) :检查流中是否没有元素满足给定条件。
  8. findFirst() :返回流中的第一个元素。
  9. findAny() :返回流中的任意一个元素。

除了上述方法之外,Stream 还提供了很多其他的操作,这些方法可以根据具体的需求进行组合和使用,以实现对集合数据的灵活处理。

示例
import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Emma");

        // 创建一个 Stream 对象,并通过 filter 操作筛选出包含字母“a”的名字
        names.stream()
             .filter(name -> name.contains("a"))
             .forEach(System.out::println);
    }
}

在这个示例中,首先创建了一个包含几个名字的 List。然后使用 stream()​ 方法将其转换为 Stream 对象,在 Stream 上调用 filter​ 方法,传入一个 Lambda 表达式作为条件,筛选出包含字母“a”的名字。最后,我们使用 forEach​ 方法打印筛选出的结果。

除了 filter​ 和 forEach​ 操作之外,Stream 还提供了很多其他的操作,如 map​、reduce​、sorted​ 等,通过这些操作,可以非常方便地进行数据处理和转换。

需要注意的是,Stream 的操作通常是惰性求值的,也就是说,在调用终结操作(如 forEach​)之前,中间操作(如 filter​、map​)不会立即执行,而是等到终结操作触发时才会执行。这种特性使得 Stream 在处理大规模数据时更加高效。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值