0

I want to group different objects types based on same content of fields incomeCode, endDate and codeRef on both classes. I omitted many fields on both classes that make each object unique for simplicity.

public class Exon  {

    private Long id;

    private IncomeCode incomeCode;

    private LocalDate endDate;

    String codeRef;

}   

public class Sup {

    private Long id;

    private IncomeCode incomeCode;

    private LocalDate startDate;

    private LocalDate endDate;

    String codeRef;

}

Exons example:

id incomdeCode endDate codeRef
1 45 01/01/2021 4
2 21 01/01/2022 5
3 33 01/01/2023 2
4 45 01/01/2021 4

Sups example:

id incomdeCode endDate codeRef
1 45 01/01/2021 4
2 21 01/01/2022 5
3 33 01/01/2023 2

Desired result : List : { {exon1, exon4, sup1}, {exon2, sup2}, {exon3, sup3} }

My attempt :

public Map<Object, List<Exon>> getExons() {
    Map<Object, List<Exon>> result = getSource1.stream()
            .flatMap(lp -> lp.getExons().stream())
            .collect(Collectors.groupingBy(e -> new KeyGroup(e.getIncomeCode(), e.getEndDate(), e.getCodeRef())
            ));
    return result;
  }

public Map<Object, List<Sup>> getSups() {
        Map<Object, List<Sup>> result = getSource2.stream()
                .flatMap(lp -> lp.getSups().stream())
               .collect(Collectors.groupingBy(e -> new 
KeyGroup(e.getIncomeCode(), e.getEndDate(), e.getCodeRef())));
        return result;
   }

 Map<Object, List<Exon>> exonList = getExons();
 Map<Object, List<Sup>> supList = getSups();
 Map<Object, List<List<?>>> objMap = new HashMap<>();

exonList.forEach((k, v) -> {
        if (objMap.containsKey(o)) {
            objMap.get(o).add(v);
        } else {
            List<List<?>> eList = new ArrayList<>();
            eList.add(v);
            objMap.put(o, eList);
        }

    });

    supList.forEach((o, v) -> {
        if (objMap.containsKey(o)) {
            objMap.get(o).add(v);
        } else {
            List<List<?>> eList = new ArrayList<>();
            eList.add(v);
            objMap.put(o, eList);
        }
    });
4
  • What should be the resulting type of the list? According to the provided class definitions exon and sup have no common super type apart from Object. BTW, class names by convention should start in with upper-case letter. Commented May 24, 2022 at 19:46
  • It would also be nicer if you would share your attempt to approach this problem. Commented May 24, 2022 at 19:48
  • Yes, exon and sup don't extend any super type apart from Object. The resulting type of list is of type Object Commented May 24, 2022 at 19:49
  • That would not give any advantage, I mean you'll be unable to access the data of this object without casting. Using Object as generic type is as bad as not use generics at all. Commented May 24, 2022 at 19:51

2 Answers 2

1

As it has been pointed out in the comments, if you need to mix different type of objects your resulting List will be a List<List<Object>>.

To group them by like that, you could use the collect() terminal operation in conjunction with a Collectors.groupingBy() which could group the objects with a key built ad-hoc with the desired fields (incomeCode, endDate and codeRef). After building the Map, you could retrieve its values, i.e. a Collection with the lists of objects, and give them in input to the Conversion Constructor of a List implementation.

List<List<Object>> listRes = new ArrayList<>(Stream.concat(listExon.stream(), listSup.stream())
        .collect(Collectors.groupingBy(obj -> {
            if (obj instanceof Exon) {
                Exon exon = (Exon) obj;
                return String.format("%s-%s-%s", exon.getIncomeCode(), exon.getEndDate(), exon.getCodeRef());
            }
            Sup sup = (Sup) obj;
            return String.format("%s-%s-%s", sup.getIncomeCode(), sup.getEndDate(), sup.getCodeRef());
        })).values());

Here there is also a link to test the code above:

https://ideone.com/OSTItQ

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

3 Comments

Thank you so much Dan, this is the expected solution. I'm wondering now when and how i can transform each group of objects [Exon{45 2021-01-01 4}, Exon{45 2021-01-01 4}, Sup{45 2021-01-01 4}] and [Exon{33 2023-01-01 2}, Sup{33 2023-01-01 2}] and [Exon{21 2022-01-01 5}, Sup{21 2022-01-01 5}] to a new object type called GlobalData. I have already a solution using a foreach loop to transform each group to his correspending GlobalData object. Any suggestion will be appreciated.
@user3072470 make a new question linking the current one. I'll be more than happy to help you.
Hi Dan, I asked a new question and here is the link : stackoverflow.com/q/72372658/3072470
1

How about something like this. You can make another subclass and group your different class item on this map

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Solution
{

    public void sol()
    {
        List<Exon> exons = new ArrayList<>();
        List<Sup> sups = new ArrayList<>();

        List<ClassWithNeededFields> list1 = exons.stream()
        .map(item -> new ClassWithNeededFields(item.getIncomeCode(), "neededField"))
        .collect(Collectors.toList());
        
        List<ClassWithNeededFields> list2 = sups.stream()
        .map(item -> new ClassWithNeededFields(item.getIncomeCode(), "neededField"))
        .collect(Collectors.toList());
        
        list1.addAll(list2);
        
        Map<IncomeCode, List<ClassWithNeededFields>> map2 = list1.stream()
                .map(item -> new ClassWithNeededFields(item.getIncomeCode(), "neededField"))
                .collect(Collectors.groupingBy(ClassWithNeededFields::getIncomeCode));

    }

    public class Exon
    {
        private IncomeCode incomeCode;

        public IncomeCode getIncomeCode()
        {
            return null;
        }
    }

    public class Sup
    {
        private IncomeCode incomeCode;

        public IncomeCode getIncomeCode()
        {
            return null;
        }
    }

    public class IncomeCode
    {

    }

    public class ClassWithNeededFields
    {
        private IncomeCode incomeCode;

        private String otherField;

        // The other needed fields. ...

        public ClassWithNeededFields(IncomeCode incomeCode, String otherField /* The other needed fields. ... */)
        {

        }

        public IncomeCode getIncomeCode()
        {
            return this.incomeCode;
        }
    }
}

3 Comments

gunescelil: i can't modify the Exon and Sup classes
Maybe you can declare a new class and only add the needed fields to that class. First you can map your Exon and Sup classes to that new Class and make a list and then you can group them
I edited my solution

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.