I have a specific problem I am trying to solve, and need some assistance with.
I have a POJO with three fields:
This POJO can be populated from the DB or an external endpoint and will return a list of said POJO. Now we end up with two seperate lists with similar infomation. These lists will be unordered and varying in size (sometimes empty).
How can I combine these two lists to create a single unique list based on the ID?
My solution is very cumbersome and ugly to read - it involved two nested loops and 3 pairs of if-else statements. Is there a better way, more efficient way of doing it.
Here is some sample code:
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Scrap2 {
public static void main(String[] args) {
MyEntity one = new MyEntity("A", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
MyEntity two = new MyEntity("B", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
MyEntity three = new MyEntity("C", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
MyEntity four = new MyEntity("D", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
List<MyEntity> listOne = Arrays.asList(one, two, three, four);
MyEntity aaa = new MyEntity("A", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
MyEntity bbb = new MyEntity("B", new Date(2020 - 1900, Calendar.OCTOBER, 25), 20);
MyEntity ccc = new MyEntity("D", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 20);
MyEntity ddd = new MyEntity("E", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 20);
List<MyEntity> listTwo = Arrays.asList(aaa, bbb, ccc, ddd);
for (MyEntity listItem : combineTwoLists(listOne, listTwo)) {
System.out.println(listItem);
}
}
private static List<MyEntity> combineTwoLists(List<MyEntity> listOne, List<MyEntity> listTwo) {
return Arrays.asList(listOne.get(0), listTwo.get(1), listOne.get(2), listTwo.get(2), listTwo.get(3));
}
}
class MyEntity {
private final String id;
private final Date date;
private final Integer weightedNumber;
public MyEntity(String id, Date date, Integer weightedNumber) {
this.id = id;
this.date = date;
this.weightedNumber = weightedNumber;
}
@Override
public String toString() {
return "MyEntity{" +
"id='" + id + '\'' +
", date=" + date +
", weightedNumber=" + weightedNumber +
'}';
}
public String getId() {
return id;
}
public Date getDate() {
return date;
}
public Integer getWeightedNumber() {
return weightedNumber;
}
}
The output should be something like this (can be unordered/unsorted):
MyEntity{id='A', date=Fri Sep 25 2020, weightedNumber=10}
MyEntity{id='B', date=Sun Oct 25 2020, weightedNumber=20}
MyEntity{id='C', date=Fri Sep 25 2020, weightedNumber=10}
MyEntity{id='D', date=Fri Sep 25 2020, weightedNumber=20}
MyEntity{id='E', date=Fri Sep 25 2020, weightedNumber=20}
You can also merge lists without duplicates in Google Sheets. Select and right-click a second range that will be merged (e.g., C2:C6) and click Copy (or use the keyboard shortcut CTRL + C).
One way to merge multiple lists is by using addAll() method of java. util. Collection class, which allows you to add the content of one List into another List. By using the addAll() method you can add contents from as many List as you want, it's the best way to combine multiple List.
Python merges two lists without duplicates could be accomplished by using a set. And use the + operator to merge it.
In python, we can use the + operator to merge the contents of two lists into a new list. For example, We can use + operator to merge two lists i.e. It returned a new concatenated lists, which contains the contents of both list_1 and list_2.
You can join both lists first then get the max by date then weightedNumber using Comparator
with BinaryOperator.maxBy
for the same id to create a map using Collectors.toMap
.Then takes the value of the map in new ArrayList.
return new ArrayList<MyEntity>(
Stream.concat(listOne.stream(), listTwo.stream())
.collect(Collectors.toMap(MyEntity::getId, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(MyEntity::getDate)
.thenComparing(MyEntity::getWeightedNumber))))
.values());
The following approach using Collectors.groupingBy
and Collectors.maxBy
should work:
groupingBy
date
and by weightedNumber
using maxBy
collector.Map.Entry<String, Optional<MyEntity>>
to List<MyEntity>
private static List<MyEntity> combineTwoLists(List<MyEntity> listOne, List<MyEntity> listTwo) {
return Stream.concat(listOne.stream(), listTwo.stream())
.collect(Collectors.groupingBy(MyEntity::getId,
Collectors.maxBy(
Comparator.comparing(MyEntity::getDate)
.thenComparing(MyEntity::getWeightedNumber))
)).entrySet()
.stream() // Stream<String, Optional<MyEntity>>
.map(Map.Entry::getValue) // take optional value
.map(Optional::get) // get from optional
.collect(Collectors.toList());
}
Here's another way to do this, without streams, yet functional:
Map<String, MyEntity> map = new LinkedHashMap<>();
Consumer<MyEntity> addAction = e -> map.merge(
e.getId(),
e,
BinaryOperator.maxBy(Comparator.comparing(MyEntity::getDate)
.thenComparing(MyEntity::getWeightedNumber)));
listOne.forEach(addAction);
listTwo.forEach(addAction);
List<MyEntity> result = new ArrayList<>(map.values());
This iterates both lists and executes the addAction
consumer on each element. The addAction
consumer consists of merging entities in a map, by applying the Map.merge
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With