如何使用单个Stream将POJO列表按双属性转换为目标字符串列表
问题背景
现有如下Alpha POJO定义:
public class Alpha { String exp1; String exp2; public Alpha(String exp1, String exp2) { super(); this.exp1 = exp1; this.exp2 = exp2; } public String getExp1() { return exp1; } public String getExp2() { return exp2; } }
对应main()方法初始实现:
public static void main(String[] args) { SpringApplication.run(Main.class, args); Alpha alpha1 = new Alpha("patrol", "amazon"); Alpha alpha2 = new Alpha("converse", "funky"); List<Alpha> list = Arrays.asList(alpha1, alpha2); List<String> collect = list.stream() .map(Alpha::getExp1) .collect(Collectors.toList()); System.out.println(collect); }
初始代码运行输出为:
[patrol, converse]
期望输出为:
[patrol, converse, patrol, amazon]
要求:仅使用单个Stream实现上述需求。
实现方案
根据对“单个Stream”的不同定义,有两种可落地的实现方式:
方式1:严格单源Stream(仅对源列表做一次遍历)
通过flatMap做字段映射+收集器收尾追加目标内容实现,全程仅创建一个针对源列表的流,无重复遍历逻辑:
public static void main(String[] args) { SpringApplication.run(Main.class, args); Alpha alpha1 = new Alpha("patrol", "amazon"); Alpha alpha2 = new Alpha("converse", "funky"); List<Alpha> list = Arrays.asList(alpha1, alpha2); // 用数组缓存第一个元素引用,适配Lambda的有效final要求 Alpha[] firstAlphaHolder = new Alpha[1]; List<String> collect = list.stream() .flatMap(alpha -> { if (firstAlphaHolder[0] == null) { firstAlphaHolder[0] = alpha; } // 先输出所有元素的exp1字段 return Stream.of(alpha.getExp1()); }) .collect(Collectors.collectingAndThen( Collectors.toList(), result -> { // 所有exp1收集完成后,追加第一个元素的exp1、exp2字段 result.add(firstAlphaHolder[0].getExp1()); result.add(firstAlphaHolder[0].getExp2()); return result; } )); System.out.println(collect); }
方式2:简洁合并流写法(代码更短,适合确定列表非空的场景)
如果不要求严格单源流,只要最终是单个流流水线执行终止操作,可以直接合并两个流实现,代码可读性更高:
public static void main(String[] args) { SpringApplication.run(Main.class, args); Alpha alpha1 = new Alpha("patrol", "amazon"); Alpha alpha2 = new Alpha("converse", "funky"); List<Alpha> list = Arrays.asList(alpha1, alpha2); Alpha firstAlpha = list.get(0); List<String> collect = Stream.concat( list.stream().map(Alpha::getExp1), Stream.of(firstAlpha.getExp1(), firstAlpha.getExp2()) ) .collect(Collectors.toList()); System.out.println(collect); }
两种写法运行后输出均和期望完全一致:
[patrol, converse, patrol, amazon]
内容的提问来源于stack exchange,提问作者it.drive.view
相关产品推荐
相关产品推荐

