Java Stream reduce - 使用 Java 8 Stream减少

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(334)   2023-06-26 07:54:18

Java Stream reduce 教程展示了如何对 Java 8 Stream执行缩减操作。

JavaStream

Java Stream 是来自支持聚合操作的源的元素序列。Stream不存储元素;元素是按需计算的。从集合、数组或 I/O 资源等数据源中使用元素。

Java Stream缩减

减少 是一种终端操作,它将Stream聚合为类型或基元。 Java 8 Stream API 包含一组预定义的缩减操作,例如 averagesummin< /code>、max 和 count,它们通过组合Stream的元素返回一个值。

Java Stream 缩减方法

Stream.reduce 是一种用于生成自定义归约操作的通用方法。

Optional<T> reduce(BinaryOperator<T> accumulator)

此方法使用关联累加函数对该Stream的元素执行归约。它返回一个 Optional 描述减少的值,如果有的话。

T reduce(T identity, BinaryOperator<T> accumulator)

该方法有两个参数:标识和累加器。如果Stream中没有元素,标识元素既是缩减的初始值,也是默认结果。累加器函数有两个参数:归约的部分结果和Stream的下一个元素。它返回一个新的部分结果。 Stream.reduce 方法返回缩减的结果。

Java Stream 内置归约

以下示例使用两个预定义的缩减操作。

JavaReduceEx.java

package com.zetcode;

import java.util.Arrays;

public class JavaReduceEx {

    public static void main(String[] args) {
        
        int vals[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
        
        int sum = Arrays.stream(vals).sum();
        System.out.printf("The sum of values: %d%n", sum);
        
        long n = Arrays.stream(vals).count();
        System.out.printf("The number of values: %d%n", n);        
    }
}

我们有一个整数数组。我们使用 Arrays.stream 从数组创建一个Stream,并执行两个缩减:sumcount。

The sum of values: 72
The number of values: 8

Java reduce 可选

带有一个参数的 reduce 方法返回一个 Optional,这是一个用于空安全的 Java 类。

Car.java

package com.zetcode;

public class Car {

    private final String name;
    private final int price;

    public Car(String name, int price) {

        this.name = name;
        this.price = price;
    }

    public int getPrice() {
        return price;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Car{name=").append(name).append(", price=")
                .append(price).append("}");

        return builder.toString();
    }
}

这是 Car 类。

JavaReduceEx2.java

package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class JavaReduceEx2 {

    public static void main(String[] args) {

        List<Car> persons = Arrays.asList(new Car("Skoda", 18544),
                new Car("Volvo", 22344),
                new Car("Fiat", 23650),
                new Car("Renault", 19700));

        Optional<Car> car = persons.stream().reduce((c1, c2)
                -> c1.getPrice() > c2.getPrice() ? c1 : c2);

        car.ifPresent(System.out::println);
    }
}

该示例创建了一个汽车对象列表。我们计算最昂贵的汽车。

Optional<Car> car = persons.stream().reduce((c1, c2)
            -> c1.getPrice() > c2.getPrice() ? c1 : c2);

从列表中,我们创建一个Stream; reduce 方法的累加器比较汽车的价格并返回较贵的汽车。

car.ifPresent(System.out::println);

如果返回的减少值不为空,我们将其打印到控制台。

Car{name=Fiat, price=23650}

下一个示例添加了其他用例。

MyUtil.java

package com.zetcode;

public class MyUtil {

    public static int add2Ints(int num1, int num2) {
        return num1 + num2;
    }
}

这是 MyUtil 类,它有一个将两个整数相加的方法。

JavaReduceEx3.java

package com.zetcode;

import java.util.stream.IntStream;

public class JavaReduceEx3 {

    public static void main(String[] args) {

        IntStream.range(1, 10).reduce((x, y) -> x + y)
                .ifPresent(s -> System.out.println(s));
        IntStream.range(1, 10).reduce(Integer::sum)
                .ifPresent(s -> System.out.println(s));
        IntStream.range(1, 10).reduce(MyUtil::add2Ints)
                .ifPresent(s -> System.out.println(s));
    }
}

我们创建三个不同的累加器函数来计算 1..10 值的总和。

IntStream.range(1, 10).reduce((x, y) -> x + y).ifPresent(s -> System.out.println(s));

在第一种情况下,我们使用 lambda 表达式进行加法运算。

IntStream.range(1, 10).reduce(Integer::sum).ifPresent(s -> System.out.println(s));

第二种情况使用内置的 Integer::sum 方法。

IntStream.range(1, 10).reduce(MyUtil::add2Ints).ifPresent(s -> System.out.println(s));

最后,我们有一个自定义的添加方法。

Java reduce with identity

正如我们已经提到的,标识既是缩减的初始值,也是Stream中没有元素时的默认结果。

User.java

package com.zetcode;

import java.time.LocalDate;
import java.time.chrono.IsoChronology;

public class User {

    private String name;
    private LocalDate dateOfBirth;

    public User(String name, LocalDate dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public LocalDate getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(LocalDate dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public int getAge() {
        return dateOfBirth.until(IsoChronology.INSTANCE.dateNow())
                .getYears();
    }

    @Override
    public String toString() {

        StringBuilder builder = new StringBuilder();
        builder.append("User{name=").append(name).append(", dateOfBirth=")
                .append(dateOfBirth).append("}");

        return builder.toString();
    }
}

这是 User 类。除了通常的属性和 getter 和 setter 之外,我们还有 getAge 方法,它使用 Java 8 日期 API 返回用户的年龄。

JavaReduceEx4.java

package com.zetcode;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class JavaReduceEx4 {
    
    public static void main(String[] args) {
        
        List<User> users = new ArrayList<>();
        users.add(new User("Frank", LocalDate.of(1979, 11, 23)));
        users.add(new User("Peter", LocalDate.of(1985, 1, 18)));
        users.add(new User("Lucy", LocalDate.of(2002, 5, 14)));
        users.add(new User("Albert", LocalDate.of(1996, 8, 30)));
        users.add(new User("Frank", LocalDate.of(1967, 10, 6)));
        
        int maxAge = users.stream().mapToInt(User::getAge)
                .reduce(0, (a1, a2) -> a1 > a2 ? a1 : a2);
        
        System.out.printf("The oldest user's age: %s%n", maxAge);
    }
}

在示例中,我们创建了一个用户列表。该示例计算最老用户的年龄。

int maxAge = users.stream().mapToInt(User::getAge)
        .reduce(0, (a1, a2) -> a1 > a2 ? a1 : a2);

我们从列表中创建一个 Java 8 Stream。使用 mapToInt 方法将Stream映射到 IntStream。最后,reduce 方法提供了一个标识值(0)和一个累加器;累加器比较年龄值并返回较大的一个。

在本文中,我们使用了 Java Stream 缩减操作。

List 所有 Java 教程.

地址:https://www.cundage.com/article/java-streamreduce.html

相关阅读

Spring Boot Vue.js 教程展示了如何使用 Vue.js 框架创建一个简单的 Spring Boot。 Vue.js Vue.js 是一个用于构建用户界面的 JavaScript ...
JavaScript 是否已经取代 Java 成为新的“一次编写,随处运行”的编程语言?这完全取决于您的观点。随着 WebAssembly 等技术的出现,Java 可以在新奇的“一次编写,随处编...
Usage of TypeScript,微软基于 JavaScript 的强类型语言, has soared compared to six years ago, according to th...
云莓将基于 Spring 构建的 Java 后端与使用 Lit 构建的 TypeScript 前端相结合,一个快速、响应式的 JavaScript 框架。基于 Vaadin Fusion 的 H...
本博客严重偏向于 GWT(和基于 GWT 的框架),但我们牢记 GWT 将来可能会被其他技术接管,因此我们始终对探索其他平台/框架持开放态度。正如他们所说,多元化可以降低风险。每种编程语言,即使...
Java JSON 教程展示了如何使用 JSON-Java 在 Java 中进行 JSON 序列化和反序列化。 JSON(JavaScript 对象显示法) 是一种轻量级数据交换格式。人类易于读...
JHipster 是一个长期存在且雄心勃勃的混合 Java 和 JavaScript 项目,致力于使用现代反应式前端简化全栈 Java 应用程序的开发。 JHipster 开发团队不断发布新版本...
解析器是强大的工具,使用 ANTLR 可以编写可用于多种不同语言的各种解析器。 在这个完整的教程中,我们将: 解释基础:什么是解析器,它可以用来做什么 查看如何设置 ANTLR 以便在 Java...
Spring Boot JSON 教程展示了如何在 Spring Boot 注释中提供 JSON 数据。 春天 是一个流行的 Java 应用程序框架,弹簧贴 是 Spring 的演变,有助于创建...
根据最近一项全球开发人员调查,在开发人员偏好方面,JavaScript 和 Python 保持了持久力,而 锈 的使用率正在上升. 5 月 4 日的一份题为“开发者国家情况,第 22nd 版”的...