How to zip two Java Lists

ぃ、小莉子 提交于 2019-12-17 04:33:10

问题


I have 2 Lists:

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

How do I create new List and zip two Lists into it?

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

回答1:


Here's Java-8 solution using the Pair class (like in @ZhekaKozlov answer):

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());
}



回答2:


Use an ArrayList of Map.Entry<String, Long>, checking that both arraylists have equal size (as it seems to be your requirement), like that:

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));
    }   
}

That's all the code you need!

Then, to iterate over the results, use something like:

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

or, you can simply get the pair at position i (keeping insertion order), by:

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

This can also hold duplicate entries, unlike the Map solution that I initially suggested, without requiring to define your own (Pair) class.




回答3:


The operation you want is called zipping.

First you need a data structure which holds two objects. Let's call it 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 + "}";
  }
}

Then you need to implement a method 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;
}

And finally the usage of zip:

zip(subjectArr, numArr);



回答4:


As per related question, you can use Guava (>= 21.0) to do this:

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());



回答5:


I agree with vefthym however if you have to do using list then create a class like below -:

class DirtyCoding{
   String subject;
   int numbr;
}

Then iterate over the your list, create object of DirtyCoding, populate it and add then add it to List<DirtyCoding>.




回答6:


Use one of the answers from Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip) to zip and apply a function at the same time

e.g. Using a zipped Stream:

<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));
     });        
}

for which you may also use Guava's Streams.zip()




回答7:


My ideas:

  • Define a class for your pairs. This makes your code extendable (i.e. if you want to add a third field).
  • Define your Lists with the convinient method Arrays.asList. It is easy to understand, short and automatically generates generic collections.
  • Use superclasses or interfaces as variable types. I used List in the example, maybe Collection would be even better. Only declare variables as ArrayList if you need the list to be so specific. That will give you the possibility to use other implementations, without having to change much code.

I would create Pair objects like this:

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:


You should create an ArrayList of List:

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



回答9:


To get an Iterator<C> from an Iterator<A>, an Iterator<B>, and a 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());
        }
    };
}



回答10:


In Java 8: You can do this in one line using Stream and Collectors class.

In 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
            }
        }


来源:https://stackoverflow.com/questions/31963297/how-to-zip-two-java-lists

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!