Google Guava “zip” two lists

前端 未结 6 2022
萌比男神i
萌比男神i 2020-12-03 13:34

Using Google Guava (Google Commons), is there a way to merge two equally sized lists into one list, with the new list containing composite objects of the two input lists?

相关标签:
6条回答
  • 2020-12-03 14:02

    You can refer to underscore-java library.

    Underscore-java is a port of Underscore.js for Java, and the zip method can achieve the goal.

    Following is a sample code & output :

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

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

    0 讨论(0)
  • 2020-12-03 14:03

    Looks like this is not currently in Guava, but is a desired feature. See this github issue, in particular Iterators.zip().

    0 讨论(0)
  • 2020-12-03 14:07

    Here's a version with no explicit iteration, but it's getting pretty ugly.

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

    It's really not much better than having explicit iteration, and you probably want some level of bounds checking to ensure that the two inputs are indeed of the same size.

    0 讨论(0)
  • 2020-12-03 14:10

    Just pretend this is a Guava method:

    for (int i = 0; i < names.size(); i++) {
        persons.add(new Person(names.get(i), ages.get(i)));
    }
    
    0 讨论(0)
  • 2020-12-03 14:10

    Here's a generic way to zip lists with vanilla Java. Lacking tuples, I opted to use a list of map entries (If you don't like to use map entries, introduce an additional class ZipEntry or something).

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

    To support arrays as well:

    @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[] {});
    }
    

    To make it more robust add precondition checks on list sizes etc, or introduce left join / right join semantics similar to SQL queries.

    0 讨论(0)
  • 2020-12-03 14:27

    As of Guava 21, this is possible via Streams.zip():

    List<Person> persons = Streams.zip(names.stream(), ages.stream(), Person::new)
                                  .collect(Collectors.toList());
    
    0 讨论(0)
提交回复
热议问题