【问题标题】:Efficiently merging lists based on a merge criteria基于合并条件有效地合并列表
【发布时间】:2025-11-29 06:15:01
【问题描述】:

我有三个排序列表,我想按照从逗号分隔的字符串派生的特定顺序将它们合并为一个。这三个列表如下所示:

List<Square> squares;
List<Ball> balls;
List<Triangle> triangles;

现在我想将所有这些列表合并到 Shape 是父类的形状列表中,添加到此列表不会破坏任何内容。

List<Shape> shapes

每个列表都按每个列表类型对象的 id 排序。合并顺序基于此字符串提供的顺序(我愿意接受更好的表示,因为这非常 hacky):

String mergeOrder = "Ball, Triangle, Squares"

基于上面的合并顺序,我想按照上面的顺序从每个列表中取出一个形状并添加到形状列表中,直到其中一个列表用完对象。此时,合并顺序应与其余列表继续。即:

Balls List:
12
16
20

Triangles List:
1

Squares List:
9
10

Merged List:
12 -> Ball
1 -> Triangle
9 -> Square
16 -> Ball
10 -> Square (Triangles ran out)
20 -> Ball (Squares ran out)

进行此类合并过程的最佳方法是什么?任何代码 sn-ps/skeleton 都会有很大帮助!

【问题讨论】:

  • 我建议使用List&lt;List&lt;Shape&gt;&gt; mergeOrder = Arrays.asList(balls, triangles, squares) 而不是那个字符串。代码也将从那里自然地遵循:只需重复遍历列表,随时弹出元素。 list.remove(0) 是一个简单的方法,尽管除非列表是 LinkedLists(这通常不是一个好主意,即使在这里)它会明显更有​​效(如果它们很长,否则不要打扰)首先反转列表。如果您不想修改原件,请先使用new ArrayList&lt;&gt;(list) 进行复制。

标签: java algorithm data-structures merge


【解决方案1】:

这是一个示例代码

public class Main {

   private static class Shape {

      private final String value;

      private final String type;

      public Shape(String type, String value) {
         this.type = type;
         this.value = value;
      }

      @Override
      public String toString() {
         return type + "[" + value + "]";
      }
   }

   public static void main(String[] args) {
      List<Shape> balls = new ArrayList<>();
      List<Shape> triangles = new ArrayList<>();
      List<Shape> squares = new ArrayList<>();
      balls.add(new Shape("Ball", "10"));
      balls.add(new Shape("Ball", "12"));
      balls.add(new Shape("Ball", "16"));
      triangles.add(new Shape("Triangle", "1"));
      squares.add(new Shape("Square", "4"));
      squares.add(new Shape("Square", "5"));

      List<Iterator<Shape>> shapes = new ArrayList<>();
      shapes.add(balls.iterator());
      shapes.add(triangles.iterator());
      shapes.add(squares.iterator());

      List<Shape> merged = new ArrayList<>();

      boolean finished = false;
      while (!finished) {
         boolean hasNext = false;
         for (Iterator<Shape> iterator : shapes) {
            hasNext = hasNext || iterator.hasNext();
            if (iterator.hasNext()) {
               merged.add(iterator.next());
            }
         }
         finished = !hasNext;
      }

      System.out.println(merged);

   }
}

更新:

流迭代:

  boolean finished = false;
  while (!finished) {
     List<Iterator<Shape>> iteratorsWithNext = shapes.stream().filter(
           s -> s.hasNext()).collect(Collectors.toList());
     iteratorsWithNext.forEach(it -> merged.add(it.next()));
     finished = iteratorsWithNext.isEmpty();
  }

输出

[Ball[10], Triangle[1], Square[4], Ball[12], Square[5], Ball[16]]

【讨论】:

  • 有什么办法可以使用Java8流来简化这里的逻辑吗?