如何压缩两个Java列表

时间:2015-08-12 11:00:32

标签: java arraylist

我有2个列表:

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

如何创建新的List并将两个列表压缩到其中?

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

10 个答案:

答案 0 :(得分:28)

这是使用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());
}

答案 1 :(得分:6)

使用Map.Entry<String, Long>的ArrayList,检查两个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));
    }   
}

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

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

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

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

Map.Entry<String, Long> entry = subjectNumArr.get(i);

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

答案 2 :(得分:4)

您想要的操作称为zipping

首先,您需要一个包含两个对象的数据结构。我们称之为Pair

public final class Pair<A, B> {
  private final A left;
  private final B right;

  public Pair(A left, B right) {
    this.left = left;
    this.right = right;
  }

  public A left() { return left; }
  public B right() { return right; }

  public String toString() {
    return "{" + left + "," + right + "}";
  }
}

然后你需要实现一个方法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<Pair<A, B>> result = new ArrayList<>();
  while (it1.hasNext() && it2.hasNext()) {
    result.add(new Pair<A, B>(it1.next(), it2.next()));
  }
  return result;
}

最后使用zip

zip(subjectArr, numArr);

答案 3 :(得分:4)

根据related question,您可以使用Guava(&gt; = 21.0)来执行此操作:

C0103:Constant name "" doesn't conform to UPPER_CASE naming style

答案 4 :(得分:1)

我同意vefthym但是如果你必须使用list然后创建一个类如下 - :

class DirtyCoding{
   String subject;
   int numbr;
}

然后遍历您的列表,创建DirtyCoding的对象,填充它并添加然后将其添加到List<DirtyCoding>

答案 5 :(得分:1)

使用Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip)中的一个答案 同时压缩和应用功能

e.g。使用压缩流:

<A,B,C>  Stream<C> zipped(List<A> lista, List<B> listb, BiFunction<A,B,C> zipper){
     int shortestLength = Math.min(lista.size(),listb.size());
     return IntStream.range(0,shortestLength).mapToObject( i -> {
          return zipper.apply(lista.get(i), listb.get(i));
     });        
}

您也可以使用Guava的Streams.zip()

答案 6 :(得分:0)

您应该创建List的ArrayList:

ArrayList<List> subjectNumArr = new ArrayList<>();
Iterator iter = subjectArr.iterator();
int count=0;
while(iter.hasNext()){
    subjectNumArr.add(Arrays.asList(iter.next(),numArr.get[count++]);
}

答案 7 :(得分:0)

我的想法:

  • 为您的对定义一个类。这使您的代码可扩展(即,如果您想添加第三个字段)。
  • 使用方便的方法 Arrays.asList 定义您的列表。 易于理解简短并自动生成通用集合。
  • 超类或接口用作变量类型。我在示例中使用了List,也许Collection会更好。如果您需要列表如此具体,则仅将变量声明为ArrayList。这将使您可以使用其他实现,而无需更改太多代码。

我会像这样创建Pair个对象:

import java.util.*;

class Pair {
    String subject;
    Long num;
}

public class Snippet {

    public static void main(String[] args) {
        List<String> subjectArr = Arrays.asList("aa", "bb", "cc");
        List<Long> numArr = Arrays.asList(2l,6l,4l);

        // create result list
        List<Pair> pairs = new ArrayList<>();

        // determine result size
        int length = Math.min(subjectArr.size(), numArr.size());

        // create pairs
        for (int position = 0; position < length; position++) {
            Pair pair = new Pair();
            pair.subject = subjectArr.get(position);
            pair.num = numArr.get(position);
            pairs.add(pair);
        }
    }
}

答案 8 :(得分:0)

要从Iterator<C>Iterator<A>Iterator<B>中获取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());
        }
    };
}

答案 9 :(得分:-2)

在Java 8中: 您可以使用Stream和Collectors类在一行中执行此操作。

在Java 7/6/5中:

List list = new ArrayList();

        if(subjectArr.size() == numArr.size())
        {
            for (int i = 0; i < subjectArr.size(); i++) { // Loop through every subject/name
                list.add(subjectArr.get(i) + " " + numArr.get(i)); // Concat the two, and add it
            }
        }