Ved*_*nth 9 java dictionary collect java-8 java-stream
我正在将一段代码从.NET移植到Java,并偶然发现了我想使用流来映射和缩减的场景.
class Content
{
private String propA, propB, propC;
Content(String a, String b, String c)
{
propA = a; propB = b; propC = c;
}
public String getA() { return propA; }
public String getB() { return propB; }
public String getC() { return propC; }
}
List<Content> contentList = new ArrayList();
contentList.add(new Content("A1", "B1", "C1"));
contentList.add(new Content("A2", "B2", "C2"));
contentList.add(new Content("A3", "B3", "C3"));
Run Code Online (Sandbox Code Playgroud)
我想编写一个函数,可以流式传输contentlist的内容并返回一个带有结果的类
content { propA = "A1, A2, A3", propB = "B1, B2, B3", propC = "C1, C2, C3" }
Run Code Online (Sandbox Code Playgroud)
我是Java的新手,所以你可能会发现一些类似C#而不是java的代码
您可以在reduce函数中为BinaryOperator使用适当的lambda 。
Content c = contentList
.stream()
.reduce((t, u) -> new Content(
t.getA() + ',' + u.getA(),
t.getB() + ',' + u.getB(),
t.getC() + ',' + u.getC())
).get();
Run Code Online (Sandbox Code Playgroud)
static Content merge(List<Content> list) {
return new Content(
list.stream().map(Content::getA).collect(Collectors.joining(", ")),
list.stream().map(Content::getB).collect(Collectors.joining(", ")),
list.stream().map(Content::getC).collect(Collectors.joining(", ")));
}
Run Code Online (Sandbox Code Playgroud)
编辑:扩展 Federico 的内联收集器,这是一个专门用于合并内容对象的具体类:
class Merge {
public static Collector<Content, ?, Content> collector() {
return Collector.of(Merge::new, Merge::accept, Merge::combiner, Merge::finisher);
}
private StringJoiner a = new StringJoiner(", ");
private StringJoiner b = new StringJoiner(", ");
private StringJoiner c = new StringJoiner(", ");
private void accept(Content content) {
a.add(content.getA());
b.add(content.getB());
c.add(content.getC());
}
private Merge combiner(Merge second) {
a.merge(second.a);
b.merge(second.b);
c.merge(second.c);
return this;
}
private Content finisher() {
return new Content(a.toString(), b.toString(), c.toString());
}
}
Run Code Online (Sandbox Code Playgroud)
用作:
Content merged = contentList.stream().collect(Merge.collector());
Run Code Online (Sandbox Code Playgroud)
处理此类任务的最通用方法是将多个收集器的结果合并为一个。
使用jOOL库,您可以拥有以下内容:
Content content =
Seq.seq(contentList)
.collect(
Collectors.mapping(Content::getA, Collectors.joining(", ")),
Collectors.mapping(Content::getB, Collectors.joining(", ")),
Collectors.mapping(Content::getC, Collectors.joining(", "))
).map(Content::new);
Run Code Online (Sandbox Code Playgroud)
这会Seq从输入列表中创建 a并结合 3 个给定的收集器来创建一个Tuple3,它只是 3 个值的持有者。然后Content使用构造函数将这 3 个值映射到 a 中new Content(a, b, c)。收集器本身只是将每个映射Content到它的a,b或c值并将结果连接在一起,并用 分隔开", "。
没有第三方的帮助,我们可以像这样创建我们自己的组合器收集器(这是基于StreamEx pairing收集器,它对 2 个收集器做同样的事情)。它将 3 个收集器作为参数,并对 3 个收集值的结果执行完成器操作。
public interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v);
}
public static <T, A1, A2, A3, R1, R2, R3, R> Collector<T, ?, R> combining(Collector<? super T, A1, R1> c1, Collector<? super T, A2, R2> c2, Collector<? super T, A3, R3> c3, TriFunction<? super R1, ? super R2, ? super R3, ? extends R> finisher) {
final class Box<A, B, C> {
A a; B b; C c;
Box(A a, B b, C c) {
this.a = a;
this.b = b;
this.c = c;
}
}
EnumSet<Characteristics> c = EnumSet.noneOf(Characteristics.class);
c.addAll(c1.characteristics());
c.retainAll(c2.characteristics());
c.retainAll(c3.characteristics());
c.remove(Characteristics.IDENTITY_FINISH);
return Collector.of(
() -> new Box<>(c1.supplier().get(), c2.supplier().get(), c3.supplier().get()),
(acc, v) -> {
c1.accumulator().accept(acc.a, v);
c2.accumulator().accept(acc.b, v);
c3.accumulator().accept(acc.c, v);
},
(acc1, acc2) -> {
acc1.a = c1.combiner().apply(acc1.a, acc2.a);
acc1.b = c2.combiner().apply(acc1.b, acc2.b);
acc1.c = c3.combiner().apply(acc1.c, acc2.c);
return acc1;
},
acc -> finisher.apply(c1.finisher().apply(acc.a), c2.finisher().apply(acc.b), c3.finisher().apply(acc.c)),
c.toArray(new Characteristics[c.size()])
);
}
Run Code Online (Sandbox Code Playgroud)
最后使用它
Content content = contentList.stream().collect(combining(
Collectors.mapping(Content::getA, Collectors.joining(", ")),
Collectors.mapping(Content::getB, Collectors.joining(", ")),
Collectors.mapping(Content::getC, Collectors.joining(", ")),
Content::new
));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5592 次 |
| 最近记录: |