Java流分组是一种将数据流分割成多个子流的技术,它可以帮助开发人员更好地处理大量数据。它的基本原理是将一个大的数据流分割成若干个小的数据流,然后再将这些小的数据流进行处理。
Java流分组有很多优势,其中最重要的一点是它可以帮助开发人员更好地处理大量数据。例如,如果你想要对一个大型文件进行处理,你可以使用Java流分组来将文件分割成若干个小文件,然后再对这些小文件进行处理。
此外,Java流分组也可以帮助开发人员减少代码量。例如,如果你想要对一个大型文件中的所有行进行相同的处理,你可以使用Java流分组来将文件中的所有行都分割成若干个子流,然后再对这些子流中的所有行都使用相同的代码来进行处理。
此外,Java流分组也能帮助开发人员减少资源占用。例如,如果你想要对一个大型文件中的所有行都使用相同的代码来进行处理(耗时操作):首先你需要读入该文件中所有行并放入内存中; 第二步你需要遍历读入内存中所有表格; 第三步你需要对读入内存中所有表格都使用相同代码来进行处理; 最后你需要将修改之后的数据写回原始文件。考虑到上面三步耗时操作占用了大量资源, 如果使用 Java 流 分 组 把 大 型 文 件 切 分 成 若 干 个 子 流, 那 么 每 个 子 流 都 可 以 由 不 含 这 三 步 过 程 的 线 程 多 路 复 用 大 量 资 源, 使得性能得到显著优化。
public static void main(String[] args) { // Create a stream of integers from 1 to 10. Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // Split the stream into two sub-streams. List<Stream<Integer> subStreams = stream.collect(Collectors.groupingBy(i -> i % 2 == 0)).values().stream().collect(Collectors.toList()); // Print the two sub-streams. System.out.println("Sub-stream 1:"); subStreams.get(0).forEach(System.out::println); System.out.println("Sub-stream 2:"); subStreams.get(1).forEach(System.out::println); }
reduce()操作组合流中的所有元素以产生单个值。
reduce操作采用两个称为种子(初始值)和累加器的参数。
累加器是一个函数。如果流是空的,种子是结果。
种子和一个元素被传递给累加器,它返回部分结果。然后将部分结果和下一个元素传递给累加器函数。
这重复,直到所有元素被传递到累加器。累加器返回的最后一个值是reduce操作的结果。
流相关接口包含两个称为reduce()和collect()的方法来执行通用reduce操作。
诸如sum(),max(),min(),count()等方法在IntStream,LongStream和DoubleStream接口中定义。
count()方法适用于所有类型的流。
Stream<T> 接口包含一个reduce()方法来执行reduce操作。该方法有三个重载版本:
T reduce(T identity, BinaryOperator<T> accumulator) <U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) Optional<T> reduce(BinaryOperator<T> accumulator)
第一个版本的reduce()方法使用一个标识和一个累加器作为参数,并将流reduce为同一类型的单个值。
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, Integer::sum); System.out.println(sum); } }
上面的代码生成以下结果。
计算所有员工的收入总和。
import java.time.LocalDate; import java.time.Month; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { double sum = Employee.persons() .stream() .map(Employee::getIncome) .reduce(0.0, Double::sum); System.out.println(sum); } } class Employee { public static enum Gender { MALE, FEMALE } private long id; private String name; private Gender gender; private LocalDate dob; private double income; public Employee(long id, String name, Gender gender, LocalDate dob, double income) { this.id = id; this.name = name; this.gender = gender; this.dob = dob; this.income = income; } public double getIncome() { return income; } public static List<Employee> persons() { Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971, Month.JANUARY, 1), 2343.0); Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972, Month.JULY, 21), 7100.0); Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973, Month.MAY, 29), 5455.0); Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974, Month.OCTOBER, 16), 1800.0); Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975, Month.DECEMBER, 13), 1234.0); Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976, Month.JUNE, 9), 3211.0); List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6); return persons; } }
上面的代码生成以下结果。
第二个版本的reduce方法如下所示允许我们执行一个map操作,随后执行reduce操作。
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
第三个参数用于组合部分结果当并行执行缩减操作时。
import java.time.LocalDate; import java.time.Month; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { double sum = Employee.persons() .stream() .reduce(0.0, (partialSum, person) -> partialSum + person.getIncome(), Double::sum); System.out.println(sum); } } class Employee { public static enum Gender { MALE, FEMALE } private long id; private String name; private Gender gender; private LocalDate dob; private double income; public Employee(long id, String name, Gender gender, LocalDate dob, double income) { this.id = id; this.name = name; this.gender = gender; this.dob = dob; this.income = income; } public double getIncome() { return income; } public void setIncome(double income) { this.income = income; } public static List<Employee> persons() { Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971, Month.JANUARY, 1), 2343.0); Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972, Month.JULY, 21), 7100.0); Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973, Month.MAY, 29), 5455.0); Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974, Month.OCTOBER, 16), 1800.0); Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975, Month.DECEMBER, 13), 1234.0); Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976, Month.JUNE, 9), 3211.0); List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6); return persons; } }
上面的代码生成以下结果。
Java Streams API支持并行映射缩减操作。
当使用以下reduce方法时,每个线程使用累加器累加部分结果。最后,组合器用于组合来自所有线程的部分结果以获得结果。
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
以下代码显示了如何顺序并行reduce操作工作。
import java.time.LocalDate; import java.time.Month; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { double sum = Employee .persons() .stream() .reduce( 0.0, (Double partialSum, Employee p) -> { double accumulated = partialSum + p.getIncome(); System.out.println(Thread.currentThread().getName() + " - Accumulator: partialSum = " + partialSum + ", person = " + p + ", accumulated = " + accumulated); return accumulated; }, (a, b) -> { double combined = a + b; System.out.println(Thread.currentThread().getName() + " - Combiner: a = " + a + ", b = " + b + ", combined = " + combined); return combined; }); System.out.println("--------------------------------------"); System.out.println(sum); sum = Employee .persons() .parallelStream() .reduce( 0.0, (Double partialSum, Employee p) -> { double accumulated = partialSum + p.getIncome(); System.out.println(Thread.currentThread().getName() + " - Accumulator: partialSum = " + partialSum + ", person = " + p + ", accumulated = " + accumulated); return accumulated; }, (a, b) -> { double combined = a + b; System.out.println(Thread.currentThread().getName() + " - Combiner: a = " + a + ", b = " + b + ", combined = " + combined); return combined; }); System.out.println(sum); } } class Employee { public static enum Gender { MALE, FEMALE } private long id; private String name; private Gender gender; private LocalDate dob; private double income; public Employee(long id, String name, Gender gender, LocalDate dob, double income) { this.id = id; this.name = name; this.gender = gender; this.dob = dob; this.income = income; } public double getIncome() { return income; } public static List<Employee> persons() { Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971, Month.JANUARY, 1), 2343.0); Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972, Month.JULY, 21), 7100.0); Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973, Month.MAY, 29), 5455.0); Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974, Month.OCTOBER, 16), 1800.0); Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975, Month.DECEMBER, 13), 1234.0); Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976, Month.JUNE, 9), 3211.0); List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6); return persons; } }
上面的代码生成以下结果。
第三个版本的reduce()如下列方法用于执行没有默认值的缩减操作。
reduce(BinaryOperator<T> accumulator)
如果流是空的,我们不能使用默认值为0。
Optional<T>
用于包装结果或不存在结果。
以下代码显示如何计算流中的整数的最大值:
import java.util.Optional; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Optional<Integer> max = Stream.of(1, 2, 3, 4, 5).reduce(Integer::max); if (max.isPresent()) { System.out.println("max = " + max.get()); } else { System.out.println("max is not defined."); } max = Stream.<Integer> empty().reduce(Integer::max); if (max.isPresent()) { System.out.println("max = " + max.get()); } else { System.out.println("max is not defined."); } } }
上面的代码生成以下结果。
以下代码打印员工列表中最高收入者的详细信息。
import java.time.LocalDate; import java.time.Month; import java.util.Arrays; import java.util.List; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<Employee> person = Employee .persons() .stream() .reduce((p1, p2) -> p1.getIncome() > p2.getIncome() ? p1 : p2); if (person.isPresent()) { System.out.println("Highest earner: " + person.get()); } else { System.out.println("Could not get the highest earner."); } } } class Employee { public static enum Gender { MALE, FEMALE } private long id; private String name; private Gender gender; private LocalDate dob; private double income; public Employee(long id, String name, Gender gender, LocalDate dob, double income) { this.id = id; this.name = name; this.gender = gender; this.dob = dob; this.income = income; } public double getIncome() { return income; } public static List<Employee> persons() { Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971, Month.JANUARY, 1), 2343.0); Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972, Month.JULY, 21), 7100.0); Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973, Month.MAY, 29), 5455.0); Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974, Month.OCTOBER, 16), 1800.0); Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975, Month.DECEMBER, 13), 1234.0); Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976, Month.JUNE, 9), 3211.0); List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6); return persons; } @Override public String toString() { String str = String.format("(%s, %s, %s, %s, %.2f)n", id, name, gender, dob, income); return str; } }
上面的代码生成以下结果。
JavaFX教程 -JavaFX时间轴动画通过更改节点的属性(如大小,位置和颜色等)创建动画。时间轴动画会随着时间的推移更新属性值。Java...
JavaFX教程 -JavaFX树视图TreeView UI控件为我们提供了一种渲染树结构的方法。 树具有包含所有分层值的根节点。import javafx.ap...
Java面向对象设计 -Java继承和构造函数构造函数不是类的成员,它们不是由子类继承的。它们用于初始化实例变量。class CSuper {pu...