Google Guava“zip”两个列表

时间:2013-09-27 00:21:22

标签: java guava

使用Google Guava(Google Commons),有没有办法将两个大小相同的列表合并到一个列表中,新列表包含两个输入列表的复合对象?

示例:

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

6 个答案:

答案 0 :(得分:25)

从Guava 21开始,这可以通过Streams.zip()

实现
List<Person> persons = Streams.zip(names.stream(), ages.stream(), Person::new)
                              .collect(Collectors.toList());

答案 1 :(得分:16)

看起来这个目前还没有Guava,但它是一个理想的功能。请参阅this github issue,特别是Iterators.zip()

答案 2 :(得分:9)

假装这是一种番石榴方法:

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

答案 3 :(得分:2)

您可以参考underscore-java library

Underscore-java是Java的Underscore.js端口,zip方法可以达到目标。

以下是示例代码&amp;输出:

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

=&GT; [[moe,30],[larry,40],[curly,50]]

答案 4 :(得分:0)

这是一个没有明确迭代的版本,但它变得非常难看。

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

它实际上没有比显式迭代好多了,你可能想要一定程度的边界检查以确保两个输入确实具有相同的大小。

答案 5 :(得分:0)

这是使用普通Java压缩列表的通用方法。缺少元组,我选择使用地图条目列表(如果您不喜欢使用地图条目,请引入其他类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查询的左连接 / 右连接语义。