Java中如何用Stream替代for循环同时遍历三个不同类型列表
问题详情
说明
- 三个列表的长度始终相等。
示例代码
public static void main(String[] args) { List<String> list1 = Arrays.asList("aaa", "bbb", "ccc"); List<Integer> list2 = Arrays.asList(1, 2, 3); List<Foo> list3 = Arrays.asList(new Foo(),new Foo(),new Foo()); for (int i=0;i<list1.size();i++) { System.out.println(output(list1.get(i),list2.get(i),list3.get(i))); } } private static String output(String first, Integer second, Foo third) { return first + second + third; } public class Foo { public int get(int i) { return i; } }
运行结果
aaa1org.example.Foo@4aa298b7 bbb2org.example.Foo@7d4991ad ccc3org.example.Foo@28d93b30
我的尝试
第一次尝试
Stream test = IntStream.range(0,list1.size()) .Stream.concat(Stream.of(list1),Stream.of(list2),Stream.of(list3)).map(this::output).map(xxx::get) .collect(Collectors.toList()) .forEach(System.out::println);
- 这段代码无法运行,我刚接触Stream。
- 不知道
xxx处该填什么,卡在这了。 - 不清楚如何在嵌套方法调用中使用
map。 - 不知道怎么收集三个不同类型的列表。
- 或许应该用map来组织它们?
使用类来组织
public class Bar { String list1; Integer list2; Foo list3; Bar(String list1Con,Integer list2Con,Foo list3Con){ list1 = list1Con; list2 = list2Con; list3 = list3Con; } public Map<String,Object> get(int index) { return new HashMap<String,Object>() {{ put("list1",list1); put("list2",list2); put("list3",list3); }}; } } List<Bar> listBar = Arrays.asList( new Bar("aaa",1,new Foo()), new Bar("bbb",2,new Foo()), new Bar("ccc",3,new Foo()) ); IntStream.range(0, listBar.size()).mapToObj(listBar::get).map(Bar::get).map(Map::values).forEach(System.out::println);
- 这段代码同样无法运行。
- 不知道怎么在
mapToObj之后给Bar::get传递参数。
核心问题
- 在Java中如何使用Stream替代for循环同时遍历三个不同类型的列表?
解决方案
直接实现方式(最贴合原需求)
利用IntStream.range生成索引流,通过索引获取三个列表对应位置的元素,再调用output方法处理即可,逻辑和原for循环完全一致:
public static void main(String[] args) { List<String> list1 = Arrays.asList("aaa", "bbb", "ccc"); List<Integer> list2 = Arrays.asList(1, 2, 3); List<Foo> list3 = Arrays.asList(new Foo(), new Foo(), new Foo()); IntStream.range(0, list1.size()) .mapToObj(i -> output(list1.get(i), list2.get(i), list3.get(i))) .forEach(System.out::println); } // 原有的output和Foo类保持不变 private static String output(String first, Integer second, Foo third) { return first + second + third; } public static class Foo { public int get(int i) { return i; } }
代码解释
IntStream.range(0, list1.size())生成从0到列表长度-1的索引流,对应原for循环的i变量。mapToObj(i -> output(...))通过lambda表达式,用当前索引取三个列表的对应元素,传入output方法生成结果字符串。forEach(System.out::println)遍历处理后的结果并打印,和原循环的输出逻辑一致。
针对你尝试中的问题修正
关于第一次尝试的错误
你误用了Stream.concat,这个方法只能合并两个流,且你是把整个列表作为单个元素传入流,完全不符合按索引取对应元素的需求,所以直接用索引流的方式更简单直接。
关于用类组织的修正思路
用类封装三组元素的思路是可行的,但你的Bar类设计冗余,不需要带索引的get方法,每个Bar对象本身就对应一组三个元素,直接提供组合结果的方法即可:
public static class Bar { String str; Integer num; Foo foo; Bar(String str, Integer num, Foo foo) { this.str = str; this.num = num; this.foo = foo; } // 直接返回组合后的字符串,和output方法逻辑一致 public String getCombined() { return str + num + foo; } } // 使用时 List<Bar> listBar = Arrays.asList( new Bar("aaa", 1, new Foo()), new Bar("bbb", 2, new Foo()), new Bar("ccc", 3, new Foo()) ); listBar.stream() .map(Bar::getCombined) .forEach(System.out::println);
内容的提问来源于stack exchange,提问作者leaf_soba
相关产品推荐
相关产品推荐

