簡體   English   中英

如何 zip 兩個 Java 列表

[英]How to zip two Java Lists

我有 2 個列表:

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

如何創建新的List和 zip 兩個 List 進去呢?

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

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

在 Java 9 之后,您可以使用Map.entry()

    public static <A, B> List<Map.Entry<A, B>> zipJava8(List<A> as, List<B> bs) {
        return IntStream.range(0, Math.min(as.size(), bs.size()))
                .mapToObj(i -> Map.entry<>(as.get(i), bs.get(i)))
                .collect(Collectors.toList());
    }

根據相關問題,您可以使用 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());

請注意,番石榴方法被注釋為@Beta ,盡管這在實踐中意味着什么取決於解釋,但該方法自版本 21.0 以來沒有改變。

使用Map.Entry<String, Long>的 ArrayList ,檢查兩個Map.Entry<String, Long>是否具有相同的大小(因為這似乎是您的要求),如下所示:

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) 類。

您想要的操作稱為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;
}

你像這樣使用它:

zip(subjectArr, numArr);

要從Iterator<A>Iterator<B>BiFunction<A, B, C>獲取Iterator<C> 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());
        }
    };
}

我同意 vefthym 但是如果你必須使用 list 然后創建一個如下所示的類:

class DirtyCoding{
   String subject;
   int numbr;
}

然后遍歷您的列表,創建DirtyCoding對象,填充它並添加然后將其添加到List<DirtyCoding>

我的想法:

  • 為您的配對定義一個類 這使您的代碼可擴展(即,如果您想添加第三個字段)。
  • Arrays.asList方法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);
        }
    }
}

使用Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip)中的答案之一同時壓縮和應用函數

例如使用壓縮流:

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

您應該創建一個列表的 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++]);
}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM