web-dev-qa-db-ja.com

グーグルグアバ「Zip」2つのリスト

Google Guava(Google Commons)を使用して、2つの同じサイズのリストを1つのリストにマージし、新しいリストに2つの入力リストの複合オブジェクトを含める方法はありますか?

例:

public class Person {
    public final String name;
    public final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "(" + name + ", " + age + ")";
    }
}

そして

List<String> names = Lists.newArrayList("Alice", "Bob", "Charles");
List<Integer> ages = Lists.newArrayList(42, 27, 31);

List<Person> persons =
    transform with a function that converts (String, Integer) to Person
System.out.println(persons);

出力します:

[(Alice, 42), (Bob, 27), (Charles, 31)]
20
Steve Kuo

Guava 21の時点で、これは Streams.Zip() :を介して可能です。

List<Person> persons = Streams.Zip(names.stream(), ages.stream(), Person::new)
                              .collect(Collectors.toList());
25
shmosel

これは現在Guavaにはないようですが、望ましい機能です。 このgithubの問題 、特にIterators.Zip()を参照してください。

16
Steve Kuo

これがGuavaメソッドであると偽ってください。

for (int i = 0; i < names.size(); i++) {
    persons.add(new Person(names.get(i), ages.get(i)));
}
10
stepanian

アンダースコア-Javaライブラリ を参照できます。

Underscore-JavaはJava用のUnderscore.jsのポートであり、Zipメソッドは目標を達成できます。

以下はサンプルコードと出力です:

$.Zip(Arrays.asList("moe", "larry", "curly"), Arrays.asList("30", "40", "50"));

=> [[moe、30]、[larry、40]、[curly、50]]

2
sheldon shen

VanillaJavaを使用してリストをZipする一般的な方法は次のとおりです。タプルがないため、マップエントリのリストを使用することにしました(マップエントリを使用したくない場合は、追加のクラスZipEntryなどを導入してください)。

public static <T1,T2> List<Map.Entry<T1,T2>> Zip(List<T1> zipLeft, List<T2> zipRight) {
    List<Map.Entry<T1,T2>> zipped = new ArrayList<>();
    for (int i = 0; i < zipLeft.size(); i++) {
        zipped.add(new AbstractMap.SimpleEntry<>(zipLeft.get(i), zipRight.get(i)));
    }
    return zipped;
}

配列もサポートするには:

@SuppressWarnings("unchecked")
public static <T1,T2> Map.Entry<T1,T2>[] Zip(T1[] zipLeft, T2[] zipRight) {
    return Zip(asList(zipLeft), asList(zipRight)).toArray(new Map.Entry[] {});
}

より堅牢にするには、リストサイズなどの前提条件チェックを追加するか、左結合/右結合 SQLクエリと同様のセマンティクスを導入します。

0
Benny Bottema

これは明示的な反復のないバージョンですが、かなり醜いものになっています。

List<Person> persons = ImmutableList.copyOf(Iterables.transform(
    ContiguousSet.create(Range.closedOpen(0, names.size()),
        DiscreteDomain.integers()),
    new Function<Integer, Person>() {
      @Override
      public Person(Integer index) {
        return new Person(names.get(index), ages.get(index));
      }
    }));

明示的な反復を行うよりも実際にはそれほど良くはありません。おそらく、2つの入力が実際に同じサイズであることを確認するために、ある程度の境界チェックが必要です。

0
Zhe