gpt4 book ai didi

java - 转换 Java Stream 并返回减少的值

转载 作者:行者123 更新时间:2023-11-30 06:01:41 24 4
gpt4 key购买 nike

假设我从不想具体化的源消耗实体流,并且我想转换元素并返回一些全局减少的值,那么 java(8) 的惯用方式是什么?

这本质上是尝试执行 reduce()collect()

示例:

class Person {
public String firstname,
public String lastname,
public int age;
}

class TeamSummary {
public List<String> fullnames, // firstname and lastname of all
public Person oldest
}

public TeamSummary getSummary(Stream<Person> personStream) {
final TeamSummary summary = new Summary();
summary.fullnames = personStream
.peek(p -> if (summary.getOldest() == null || summary.getOldest.age < p.age) {
summary.oldest = p;
})
.map(p -> p.firstname + ' ' + p.lastname)
.collect(toList());
return summary;
}

在 peek 方法内与流外的变量交互看起来很难看,但是有什么好的替代方案,看来我需要结合 collect()reduce().

如果我想从整个流中获取减少的值(例如平均年龄)和过滤列表(例如 18 岁以上的人员),情况会变得更糟。如果 TeamSummary 是一个不可变类,并且需要额外的可变变量,情况也会变得更糟。

在这种情况下,在stream.iterator()上使用while循环来避免流方法和变量的耦合更为惯用?或者使用reduce 到像(最旧的,累积的)这样的元组是很自然的。

我知道这个问题是一个意见问题,除非有一种明显的方法(比如特殊的收集器)可以优雅地解决这个问题。

最佳答案

所以您想将您的集合减少为单个值?这就是 Collectors.reducing 发挥作用的地方(替代方案:您可以使用 Stream.reduce 但进行其他修改)。此外,您希望以某种方式聚合您的值,并拥有完美的累加器:TeamSummary

现在,在下面的代码中我做了以下调整:

  • Team Summary 具有reduce 所需的合并/身份函数,因为它充当累加器
  • 我使用Null Object而不是针对不存在的人的 null ,这使得代码在没有 null 检查的情况下更具可读性(转换器期间的 NPE 是问题之一)。您是否考虑过如果流为空时的输出?
  • 为了方便起见,我添加了一个 Person 构造函数。但请考虑使用 getter 和 Final 字段(即使您认为 getters 和整个假封装都是样板:您可以使用方法引用,例如传递给比较器,但不能使用字段引用)

这是代码:

static class Person {
public String firstname;
public String lastname;
public int age;

public Person(String firstname, String lastname, int age) {
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}

public static Person getNullObjectYoung() {
return new Person("", "", 0);
}
}

static class TeamSummary {
public List<String> fullnames;
public Person oldest;

public static TeamSummary merge(TeamSummary lhs, TeamSummary rhs) {
TeamSummary result = new TeamSummary();
result.fullnames = new ArrayList<>();
result.fullnames.addAll(lhs.fullnames);
result.fullnames.addAll(rhs.fullnames);
result.oldest = Comparator.<Person, Integer>comparing(p -> p.age).reversed()
.compare(lhs.oldest, rhs.oldest) < 0
? lhs.oldest
: rhs.oldest;
return result;
}

public static TeamSummary of(Person person) {
TeamSummary result = new TeamSummary();
result.fullnames = new ArrayList<>();
result.fullnames.add(person.firstname + " " + person.lastname);
result.oldest = person;
return result;
}

public static TeamSummary identity() {
TeamSummary result = new TeamSummary();
result.fullnames = new ArrayList<>();
result.oldest = Person.getNullObjectYoung();
return result;
}
}

public static void main(String[] args) {
Stream<Person> personStream = Arrays.asList(
new Person("Tom", "T", 32),
new Person("Bob", "B", 40))
.stream();

TeamSummary result = personStream.collect(
Collectors.reducing(
TeamSummary.identity(),
TeamSummary::of,
TeamSummary::merge
));
System.out.println(result.fullnames + " " + result.oldest.age);

}

注意:您要求的是 java 8 版本。也许在 java 12 中,您还可以使用Collectors.teeing,因为您基本上希望同时进行两种不同的缩减(为此我们目前可以利用累加器)。


编辑:还添加了 Stream.reduce 的解决方案,它需要 BiFunction (summary, person) -> person:

static class TeamSummary {

...

public TeamSummary include(final Person person) {
final TeamSummary result = new TeamSummary();
result.fullnames = new ArrayList<>(fullnames);
result.fullnames.add(person.firstname + " " + person.lastname);
result.oldest = Comparator.<Person, Integer> comparing(p -> p.age).reversed()
.compare(oldest, person) < 0
? oldest
: person;
return result;
}
}

public static void main(final String[] args) {
...

final TeamSummary reduced = personStream.reduce(
TeamSummary.identity(),
TeamSummary::include,
TeamSummary::merge);
}

关于java - 转换 Java Stream 并返回减少的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56927517/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com