You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。
  1. 不知道xxx处该填什么,卡在这了。
  2. 不清楚如何在嵌套方法调用中使用map。
  3. 不知道怎么收集三个不同类型的列表。
  • 或许应该用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);
  • 这段代码同样无法运行。
  1. 不知道怎么在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;
    }
}

代码解释

  1. IntStream.range(0, list1.size())生成从0到列表长度-1的索引流,对应原for循环的i变量。
  2. mapToObj(i -> output(...))通过lambda表达式,用当前索引取三个列表的对应元素,传入output方法生成结果字符串。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:15:07