Java 使用流api在字段上而不是对象上循环
我想将Java 8的流api用于以下练习:Java 使用流api在字段上而不是对象上循环,java,collections,java-stream,Java,Collections,Java Stream,我想将Java 8的流api用于以下练习: 给定人员列表 Person是一个简单的POJO,具有名称(字符串)和年龄(int)属性 构造以下字符串Names=[joe,diana,thomas]&Ages=[34,52,19] 使用streams,我可以轻松做到以下几点: String result = persons.stream() .map(p -> "(" + p.getName() + "," + p.getAge() + ")") .collectors(C
- 给定
人员列表
是一个简单的POJO,具有名称(字符串)和年龄(int)属性Person
- 构造以下字符串
Names=[joe,diana,thomas]&Ages=[34,52,19]
String result = persons.stream()
.map(p -> "(" + p.getName() + "," + p.getAge() + ")")
.collectors(Collectors.joining("&","persons=[","]");
这将给出persons=[(joe,34)&(diana,52)&(thomas,19)]
,但我不知道如何在多个person对象的字段上连接,而不是在每个person对象的属性上连接。这就像我需要将人员平面映射到一个属性,然后将人员列表第二次平面映射到下一个属性,然后合并这些输出。这个的语法是什么
Person类非常简单。如果可能的话,我想要一个解决方案,它的编写方式是使用反射在类的所有字段上循环,而不是只检查硬编码的“name”和“age”字段。假设所有字段都是简单的属性,如String或int(没有嵌套的类或集合)。我想如果有一个class
Person
(如您所述),您需要一个自定义收集器来完成以下任务:
String result = List.of(new Person(1, "david"), new Person(33, "eugene"))
.stream()
.parallel()
.collect(Collector.of(
() -> new StringJoiner[]{new StringJoiner(",", "[", "]"), new StringJoiner(",", "[", "]")},
(sj, per) -> {
sj[0] = sj[0].add("" + per.getAge());
sj[1] = sj[1].add(per.getName());
},
(left, right) -> {
left[0] = left[0].merge(right[0]);
left[1] = left[1].merge(right[1]);
return left;
},
x -> "Names = " + x[1].toString() + "&Ages = " + x[0].toString()
));
你可以用
String result = persons.stream()
.flatMap(p -> Stream.of(new AbstractMap.SimpleEntry<>(true, p.getName()),
new AbstractMap.SimpleEntry<>(false, ""+p.getAge())))
.collect(Collectors.collectingAndThen(
Collectors.partitioningBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.joining(",", "[", "]"))),
m -> "Names="+m.get(true)+"&Ages="+m.get(false)));
您可能需要编写自己的
收集器
。如果流的对象不都是同一类型的,您还需要决定结果应该是什么。对于两个字段(如名称和年龄),您可以使用“Collectors.toMap”和“Collectors.CollectingAnd”编写一个简单的解决方案,但在更一般的情况下,它会变得更复杂,您可能需要像@Andreas所说的那样编写自定义收集器。@只有在绝对确定名称是唯一的情况下,才能使用alainlompo映射。因为世界上不止一个(或多个),你不能保证这一点,所以地图不是一个好的选择。
String result = persons.stream()
.flatMap(p -> Stream.of(new AbstractMap.SimpleEntry<>("Names", p.getName()),
new AbstractMap.SimpleEntry<>("Ages", ""+p.getAge())))
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.joining(",", "[", "]"))),
m -> m.entrySet().stream()
.map(e -> e.getKey()+"="+e.getValue()).collect(Collectors.joining("&"))));