简体   繁体   中英

Join list of 2 different object to a list of a third object using Java 8 streams

I came a cross a problem I didn;t manage to solve...

I have 3 types of objects

  1. MyObject1 - with fields id and name
  2. MyObject2 - with fields id and error
  3. MyJoinObject - with fields id, name and error

I have 2 lists:

  1. List of MyObject1
  2. List of MyObject2

I want to create a third list of MyJoinObject, which is a join of the 2 lists. There will be MyJoinObject objects as MyObject1 objects, but they will also contain the error if exists (joined by id). I want to do that with Java 8 streams .

You can do something like that :

List<MyJoinObject> result = 
    list1.stream().map( o1 -> {
        Optional<MyObject2> error = list2.steam()
                                         .filter( o2 -> o2.getId() == o1.getId() )
                                         .findAny();
        if ( error.isPresent() ) 
            return new MyJoinObject( o1.getId(), o1.getName(), error.get().getError() );      

        return new MyJoinObject( o1.getId(), o1.getName() );

    } ).collect( Collectors.toList() );

You can also construct a hasmap of errors mapped by id before doing that by doing :

final Map<Integer, MyObject2> errorsById = 
     list2.stream( )
          .collect( Collectors.toMap( MyObject2::getId, Function.identity( ) ) );

If you do that, you can use this map by calling methods containsKey( ) or get( ) to retreive the error

Something like this could work (although I didn't verify):

public static void main(String[] args) {
    List<MyObject1> object1list = new ArrayList<>(); // fill with data
    List<MyObject2> object2list = new ArrayList<>();// fill with data

    List<MyJoinObject> joinobjectlist = new ArrayList<>();

    object1list.stream().forEach(
            o1 -> object2list.stream().filter(
                    o2-> o1.getId()==o2.getId()
                    ).forEach(o2->joinobjectlist.add(
                            new JoinObject(o2.getId(), o1.getName(), o2.getError()))
                            )
            );

}

For your information:

public static void main(String[] args) {

    List<MyObject1> myObject1s = new ArrayList<>();
    List<MyObject2> myObject2s = new ArrayList<>();

    // convert myObject2s to a map, it's convenient for the stream
    Map<Integer, MyObject2> map = myObject2s.stream().collect(Collectors.toMap(MyObject2::getId, Function.identity()));

    List<MyJoinObject> myJoinObjects = myObject1s.stream()
                                                 .map(myObject1 -> new MyJoinObject(myObject1, map.get(myObject1.getId()).getError()))
                                                 .collect(Collectors.toList());

}

Of course, there should be a new construction for MyJoinObject, like this:

public MyJoinObject(MyObject1 myObject1, String error){
    this.id = myObject1.getId();
    this.name = myObject1.getName();
    this.error = error;
}

That's all. :P

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM