如何压缩两个Java列表

aha*_*ian 21 java arraylist

我有2个列表:

List<String> subjectArr = Arrays.asList<String>("aa", "bb", "cc");
List<Long> numArr = Arrays.asList<Long>(2L, 6L, 4L);
Run Code Online (Sandbox Code Playgroud)

如何创建新的List和拉链两个列表?

List<?> subjectNumArr = zip(subjectArr, numArr);
// subjectNumArr == [{'aa',2},{'bb',6},{'cc',4}]
Run Code Online (Sandbox Code Playgroud)

Tag*_*eev 30

这是使用Pair该类的Java-8解决方案(如@ZhekaKozlov答案):

public static <A, B> List<Pair<A, B>> zipJava8(List<A> as, List<B> bs) {
    return IntStream.range(0, Math.min(as.size(), bs.size()))
            .mapToObj(i -> new Pair<>(as.get(i), bs.get(i)))
            .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

  • 注意:如果列表不提供有效的随机访问(例如:链表),则每个 get() 都将是 O(n) 而不是 O(1) (5认同)
  • 我想您应该在 Java 9 示例中将“zipJava8”重命名为“zipJava9”。 (2认同)

Sol*_*cko 12

Iterator<C>要从 an Iterator<A>、 anIterator<B>和 a获取 an BiFunction<A, B, C>

public static <A, B, C> Iterator<C> map(Iterator<A> a, Iterator<B> b, BiFunction<A, B, C> f) {
    return new Iterator<C>() {
        public boolean hasNext() {
            return a.hasNext() && b.hasNext(); // This uses the shorter of the two `Iterator`s.
        }

        public C next() {
            return f.apply(a.next(), b.next());
        }
    };
}
Run Code Online (Sandbox Code Playgroud)


tkr*_*use 8

根据相关问题,您可以使用 Guava (>= 21.0) 来执行此操作:

List<String> subjectArr = Arrays.asList("aa", "bb", "cc");
List<Long> numArr = Arrays.asList(2L, 6L, 4L);
List<Pair> pairs = Streams.zip(subjectArr.stream(), numArr.stream(), Pair::new)
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

请注意,guava 方法被注释为@Beta,尽管这在实践中意味着什么取决于解释,但该方法自 21.0 版以来没有改变。


vef*_*hym 6

使用ArrayList Map.Entry<String, Long>,检查两个arraylists是否具有相同的大小(因为它似乎是你的要求),如下所示:

List<Map.Entry<String,Long>> subjectNumArr = new ArrayList<>(numArr.size());
if (subjectArr.size() == numArr.size()) {
    for (int i = 0; i < subjectArr.size(); ++i) {
        subjectNumArr.add(new AbstractMap.SimpleEntry<String, Long>(subjectArr.get(i), numArr.get(i));
    }   
}
Run Code Online (Sandbox Code Playgroud)

这就是你需要的所有代码!

然后,要迭代结果,请使用以下内容:

for (Map.Entry<String, Long> entry : subjectNumArr) {
    String key = entry.getKey(); 
    Long value = entry.getValue();
}
Run Code Online (Sandbox Code Playgroud)

或者,你可以简单地通过以下方式获得位置i(保持插入顺序)的对:

Map.Entry<String, Long> entry = subjectNumArr.get(i);
Run Code Online (Sandbox Code Playgroud)

与我最初建议的Map解决方案不同,这也可以保留重复的条目,而无需定义自己的(Pair)类.


Zhe*_*lov 5

您想要的操作称为zipping

你需要实现一个方法zip

public static <A, B> List<Pair<A, B>> zip(List<A> as, List<B> bs) {
  Iterator<A> it1 = as.iterator();
  Iterator<B> it2 = bs.iterator();
  List<Map.Entry<A, B>> result = new ArrayList<>();
  while (it1.hasNext() && it2.hasNext()) {
    result.add(Map.entry(it1.next(), it2.next()));
  }
  return result;
}
Run Code Online (Sandbox Code Playgroud)

你像这样使用它:

zip(subjectArr, numArr);
Run Code Online (Sandbox Code Playgroud)

  • 静态工厂方法 `makePair&lt;A,B&gt;(A left, B right)` 而不是 Pair 中的构造函数将使这一行成为可能:`result.add(Pair.makePair(it1.next(), it2.next() )));`(无需重复类型) (2认同)