new Java List of objects by matching entries in two other lists

  • A+

suppose I have these two lists

List<Person> persons = Arrays.asList(                 new Person(1, "Mike", "Canada"),                 new Person(2, "Jill", "England"),                 new Person(3, "Will", "Whales"),                 new Person(4, "Mary", "Spain"));   List<Metadata> metadata= Arrays.asList(                 new metadata(1, "2000-01-01", "Naturalized", "Bachelor's of Arts"),                 new metadata(2, "2001-01-01", "ExPat", "Masters of Chemestry"),                 new metadata(3, "2017-05-01", "Citizen", "Buiness Management"),                 new metadata(4, "2018-04-16", "Work Visa", "Nursing")); 

where the end result is a new list:

List<PersonWithMetadata> personsAndMEtadata = Arrays.asList(                 new PersonWithMetadata(1, "Mike", "Canada", "2000-01-01", "Naturalized", "Bachelor's of Arts"),                 new PersonWithMetadata(2, "Jill", "England", "2001-01-01", "ExPat", "Masters of Chemestry"),                 new PersonWithMetadata(3, "Will", "Whales", "2017-05-01", "Citizen", "Buiness Management"),                 new PersonWithMetadata(4, "Mary", "Spain", "2018-04-16", "Work Visa", "Nursing")); 

I am trying to find a Java streams way of combining the first two lists into the third--like an SQL join on the first input being an id number. It seems like there should be a way to do this, but I'm at a loss. how is this done? Also, suppose that there is at most one match between the two input lists.


YCF_L's solution should work, but it's an O(n2) solution. An O(n) solution could be achieved by converting one list to map from the id to the object, and then iterating over the other and getting the matching value from the map:

Map<Integer, Person> personMap =, Function.identity());  List<PersonWithMetadata> result =             .map(m -> new PersonWithMetadata(personMap.get(m.getId()), m)             .collect(Collectors.toList()); 

In the sample data the lists have matching objects in matching order. If this assumption is true for the real problem too, the solution could be must easier - you could stream the indexes and get the corresponding values from the lists:

List<PersonWithMetadata> result =      IntStream.reange(0, persons.size())              .map(i -> new PersonWithMetadata(persons.get(i), metadata.get(i))              .collect(Collectors.toList()); 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: