【问题标题】:Efficient way to iterate over two related ArrayLists?迭代两个相关 ArrayList 的有效方法?
【发布时间】:2021-07-05 04:29:40
【问题描述】:

我正在寻找一种干净简单的方法来迭代两个直接相关的 ArrayList,其中一个的每个索引都映射到另一个的索引(在关系中)。

目前,我正在通过一个简单的 for 循环执行此操作,我尝试查看 lambdas 和 for-each 循环,但没有看到将其同时应用于两个相同列表的方法大小。

firstList:["Blue", "Red", "Green"]

secondList:["Sky", "Roses", "Grass"]

for(int i = 0; i < firstList.size(); i++){
    System.out.println(firstList.get(i) + " " + secondList.get(i));
}

结果:

Blue Sky
Red Roses
Green Grass

有没有办法使用 lambda 或 for-each 循环同时有效地迭代两个列表以避免使用 for 循环?

【问题讨论】:

  • Streams 和 lambdas肯定比for 循环更糟糕。也许并没有我曾经想的那么糟糕,我以前是一个激烈而顽固的反流运动者。也许只是稍微更糟。但更糟糕的是。

标签: java list loops collections


【解决方案1】:

您所拥有的已经非常高效(假设您使用的是 ArrayList),简洁易读。但是,这种类型的场景:

我正在寻找一种干净简单的方法来迭代两个 ArrayList 直接相关的一个索引的每个索引都映射到索引 另一个(在关系中)。

在您的情况下,通常需要一个定义关系的类:

public class MyC {
    private final String color;
    private final String object;

    public MyC(String color, String object) {
        this.color = color;
        this.object = object;
    }
    public String getColor(){
        return color;
    }
    public String getObject(){
        return object;
    }

    @Override
    public String toString() {
        return "MyC{" +
                "color='" + color + '\'' +
                ", object='" + object + '\'' +
                '}';
    }
} 

那么这两个列表将合二为一:

List<MyC> list = List.of(new MyC("Blue", "Sky"), new MyC("Red", "Roses"), new MyC("Green", "Grass") );

然后你可以使用:

list.forEach(System.out::println);

【讨论】:

    【解决方案2】:

    Answer by dreamcrash 是正确的:虽然您可以循环一对数组,但您应该通过定义自己的类来利用 Java 作为 OOP 语言。

    记录

    使用新的records 功能在 Java 16 中定义这样的类更加简单。当您的课程的主要目的是透明且不可变地传递数据时,将其编写为记录。

    默认情况下,记录非常简短。编译器隐式创建构造函数、getter、equals & hashCodetoString。您只需要声明每个成员字段的类型和名称。

    record ColorNoun ( String color , String noun ) {}
    

    像传统类一样使用记录。使用new 进行实例化。

    ColorNoun blueSky = new ColorNoun ( "Blue" , "Sky" ) ;
    

    请注意,记录可以在方法中本地声明,也可以像常规类一样单独声明。

    【讨论】:

      【解决方案3】:

      您可以使用“范围”语句通过 lambda 表达式迭代索引。

      https://www.baeldung.com/java-stream-indices

      像这样:

      List<String> firstList = Arrays.asList("Blue","Red","Green");
      List<String> secondList = Arrays.asList("Sky","Roses","Grass");
      
      IntStream
          .range(0, firstList.size())
          .forEach(index -> 
              System.out.println(String.format("%s %s", firstList.get(index), secondList.get(index)))
          );
      

      这基本上是相同的方法 - 只是使用 lambdas。

      摆脱基于索引的访问的唯一方法是使用不同的数据结构或使用交替迭代技术,如其他答案所示。

      【讨论】:

      • 人们一直使用System.out.println(String.format(…))而不是System.out.printf(…)的原因是什么?并不是说使用"%s %s" 进行格式化是对更简单、更高效的firstList.get(index) + " " + secondList.get(index) 的改进。
      【解决方案4】:

      如果您的意图只是避免使用for 循环,那么您可以尝试以下方法:

      Iterator<String> iterator = secondList.iterator();
      firstList.forEach(s -> System.out.println(s + " " + iterator.next()));
      

      或者甚至添加到StringBuilder,然后在最后显示结果。

      【讨论】:

        【解决方案5】:

        所有其他答案都是正确的,首选解决方案应始终是 @Basil Bourque 显示的解决方案,但正如其他人在 cmets 中指出的那样,使用索引迭代非基于数组的列表效率不高。但是,使用迭代器进行迭代应该(每个实现都可以提供有效的实现)是。

        这是一个如何使用迭代器迭代 2 个列表的示例:

        import java.util.Arrays;
        import java.util.Iterator;
        import java.util.List;
        import java.util.function.BiConsumer;
        
        public class IterateTwoListsExample {
        
            public static void main(String[] args) {
                List<String> firstList = Arrays.asList("Blue","Red","Green");
                List<String> secondList = Arrays.asList("Sky","Roses","Grass");
        
                forEach(firstList, secondList, (first, second) -> System.out.printf("%s %s%n", first, second));
            }
        
            public static <T0, T1> void forEach(List<? extends T0> first, List<? extends T1> second, BiConsumer<? super T0, ? super T1> consumer) {
                final Iterator<? extends T0> firstIt = first.iterator();
                final Iterator<? extends T1> secondIt = second.iterator();
        
                while (firstIt.hasNext() && secondIt.hasNext()) {
                    consumer.accept(firstIt.next(), secondIt.next());
                }
            }
        }
        
        

        【讨论】:

          猜你喜欢
          • 2019-05-05
          • 2017-03-06
          • 1970-01-01
          • 1970-01-01
          • 2013-11-22
          • 1970-01-01
          • 1970-01-01
          • 2016-08-23
          • 1970-01-01
          相关资源
          最近更新 更多