How can I concatenate two streams and return a list with a different type?

I have two streams and I want to combine them into a list with different ie I have a hashmap

Map<String, List<String>> citiesByZip = new HashMap<>();

      

which store this data

Alameda [95246, 95247]
Colusa [95987]

      

list of persons

  class Person {
    private String firstName;
    private String lastName;
    private int income;
    private int zipCode;



 People(String firstName, String lastName, int income, int zipCode) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.income = income;
        this.zipCode = zipCode;
    }

    public String getFirstName() {
        return firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public int getIncome() {
        return income;
    }
    public int getZipCode() {
        return zipCode;
    }
}
 List<Person> persons= new ArrayList<>();

      

which store this data

Junior Jane 20000 95246
Junior Jane 30000 95246
Joseph James 50000 95247
Patricia Allen 60000 95247
Opal Campbell 70000 95987
Dorothy Rook 80004 95987
Mary Nelson 80000 23666

      

I want to match each person on the list in the counties hashmap to find which count person lives in

List <FinalObject> finalObjects= new  ArrayList<>();
finalObjects = Stream.concat(peopleStream.stream(), citiesByZip.entrySet().stream())
                .collect(Collectors.toMap(
                ))

      

this list should return a list of target objects like this

Junior Jane 20000 Alameda
Junior Jane 30000 Alameda
Joseph James 50000 Alameda
           .
           .
           etc

      

I know I can make this work in Java 7 with tradition loops, but I was wondering if I could do the same thing in java 8 using stream and lambda

+3


source to share


1 answer


First, you need a data structure to efficiently find a specific zip code, as Map<String, List<String>>

it is not suitable for that. You can convert it like

Map<Integer,String> zipToCity = citiesByZip.entrySet().stream()
    .flatMap(e -> e.getValue().stream().map(Integer::valueOf)
                   .map(zip -> new AbstractMap.SimpleEntry<>(zip, e.getKey())))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

      

Alternatively, you can use

Map<Integer,String> zipToCity = citiesByZip.entrySet().stream()
    .collect(HashMap::new,
            (m,e) -> e.getValue().forEach(zip -> m.put(Integer.valueOf(zip), e.getKey())),
            Map::putAll);

      

which doesn't need temporary instances AbstractMap.SimpleEntry

, but looks like a normal iterative solution. In fact, for consistent use, the loop is actually simpler.

Then you can convert instances Person

to instances FinalObject

using a single thread operation. Since you did not specify the class FinalObject

, I am assuming

class FinalObject {
    private String firstName, lastName, city;
    private int income;
    FinalObject(String firstName, String lastName, int income, String city) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.income = income;
        this.city = city;
    }

    public String getFirstName() {
        return firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public int getIncome() {
        return income;
    }
    public String getCity() {
        return city;
    }
    @Override public String toString() {
        return firstName+" "+lastName+" "+income+" "+city;
    }
}

      



With this definition, you can do a zip search conversion like

List<FinalObject> finalObjects = persons.stream()
    .map(p -> new FinalObject(p.getFirstName(), p.getLastName(),
                  p.getIncome(), zipToCity.getOrDefault(p.getZipCode(), "Unknown")))
    .collect(Collectors.toList());

      

Although it might be helpful to use delegation instead:

class FinalObject {
    private Person p;
    String city;

    FinalObject(Person p, String city) {
        this.p = p;
        this.city = city;
    }

    public String getFirstName() {
        return p.getFirstName();
    }
    public String getLastName() {
        return p.getLastName();
    }
    public int getIncome() {
        return p.getIncome();
    }
    public String getCity() {
        return city;
    }
    @Override public String toString() {
        return getFirstName()+" "+getLastName()+" "+getIncome()+" "+city;
    }
}

      

List<FinalObject> finalObjects = persons.stream()
    .map(p -> new FinalObject(p, zipToCity.getOrDefault(p.getZipCode(), "Unknown")))
    .collect(Collectors.toList());

      

+6


source







All Articles