2

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.

3
  • 5
    It would be really helpful if you'd give a minimal reproducible example including what you've tried so far. What happens if there are multiple errors for a single MyObject1? Commented Apr 14, 2016 at 6:07
  • Each list of objects contains a unique objects by the id attribute, so object can have one error or none. Commented Apr 14, 2016 at 6:18
  • 2
    Hmm. In LINQ (.NET) this would be trivial. Unfortunately I'm not sure of the equivalent for a group join in Java streams. I would still strongly encourage you to update your question with an minimal reproducible example which will make it easier for people to help you. Include sample input data (hard-coded) and expected output data... along with anything you've already tried. Commented Apr 14, 2016 at 6:23

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

Comments

2

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

}

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.