Home > front end >  Grouping objects of different types based on common fields
Grouping objects of different types based on common fields

Time:05-25

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

CodePudding user response:

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

CodePudding user response:

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;
        }
    }
}
  • Related