I have ArrayList of objects
public static void prepareList() {
Author a1 =new Author();
Author a2 =new Author();
Author a3 =new Author();
Author a4 =new Author();
Author a5 =new Author();
Author a6 =new Author();
Author a7 =new Author();
a1.setTransId("1111111");
a1.setCountryCode("US");
a1.setCurrencyUSD(100000);
a1.setExccessAmount(100000);
a2.setTransId("1111111");
a2.setCountryCode("US");
a2.setCurrencyUSD(100000);
a2.setExccessAmount(100000);
a3.setTransId("1111111");
a3.setCountryCode("IN");
a3.setCurrencyUSD(100000);
a3.setExccessAmount(100000);
a4.setTransId("222222");
a4.setCountryCode("US");
a4.setCurrencyUSD(100000);
a4.setExccessAmount(100000);
a5.setTransId("222222");
a5.setCountryCode("US");
a5.setCurrencyUSD(100000);
a5.setExccessAmount(100000);
a6.setTransId("3333333");
a6.setCountryCode("US");
a6.setCurrencyUSD(100000);
a6.setExccessAmount(100000);
a7.setTransId("444444");
a7.setCountryCode("US");
a7.setCurrencyUSD(100000);
a7.setExccessAmount(100000);
Collection<Author> arrayListofObjects = new ArrayList<Author>();
arrayListofObjects.add(a1);
arrayListofObjects.add(a2);
arrayListofObjects.add(a3);
arrayListofObjects.add(a4);
arrayListofObjects.add(a5);
arrayListofObjects.add(a6);
arrayListofObjects.add(a7);
System.out.println("arrayListofObjects Size = " arrayListofObjects.size());
Map<String, List<Author>> mapList = arrayListofObjects.stream().collect(Collectors.groupingBy(authorObj -> authorObj.getTransId() "_"
authorObj.getCountryCode()));
System.out.println("Map Size = " mapList.size());
for(Entry<String, List<Author>> listobj : mapList.entrySet()) {
String key = listobj.getKey();
//System.out.println("key = " key);
List<Author> contraList = mapList.get(key);
//System.out.println("contraList = " contraList.size());
//TODO if the list size is >1 then add CurrencyUSD and ExccessAmount, make as one object in that list (Size should be 1)
if(contraList.size()>1) {
System.out.println("key = " key);
System.out.println("contraList = " contraList.size());
}
}
Here a1,a2 and a4,a5 are having same TransId, CountryCode I want to make them one obj adding CurrencyUSD, ExccessAmount achieving less time consuming way as I will be dealing with large data. Maybe using comparator, Streams.
I see one similar question but its time consuming not working as expected.
CodePudding user response:
You were in the right track by grouping, just add a reducing collector:
Map<String, Author> mapList =
arrayListofObjects.stream()
.collect(Collectors.groupingBy(authorObj -> authorObj.getTransId() "_" authorObj.getCountryCode(),
Collectors.reducing(new Author("", "", 0, 0),
(x,y) -> {
y.setCurrencyUSD(y.currencyUSD x.currencyUSD);
y.setExccessAmount(y.exccessAmount x.exccessAmount);
return y;
})));
final Collection<Author> aggregated = new ArrayList<>(mapList.values());
CodePudding user response:
Another way can be
List<Author> out = arrayListofObjects.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(e->e.getTransId() e.getCountryCode(), Function.identity(), (a, b) -> {
a.setCurrencyUSD(a.getCurrencyUSD() b.getCurrencyUSD());
a.setExccessAmount(a.getExccessAmount() b.getExccessAmount());
return a;
}), m -> new ArrayList<>(m.values())));
out.forEach(System.out::println);
CodePudding user response:
For comparison, I'll also add a version not using streams:
//map of unquie authors based on transid and country code, keep order of authors as per the list
Map<String, Author> uniqueAuthors = new LinkedHashMap<>();
//iterate over the incoming list of authors
for( Author author : arrayListofObjects ) {
//get the author based on "<transid>_<country_code>"
//if the author doesn't exist create a new copy using the incoming key and 0 values
Author uniqueAuthor = uniqueAuthors .computeIfAbsent(author.getTransId() "_" author.getCountryCode(),
key -> new Author(author.getTransId(), author.getCountryCode(), 0,0 );
//add the currency into the unique author
uniqueAuthor.setCurrencyUSD(uniqueAuthor.getCurrencyUSD() author.getCurrencyUSD());
//add the excess amount into the unique author
uniqueAuthor.setExccessAmount(uniqueAuthor.getExccessAmount() author.getExccessAmount());
}
//create a list of unique authors that keeps the original ordering
List<Author> listOfUniqueAuthors = new ArrayList<>(uniqueAuthors.values());
Quick description of this approach:
LinkedHashMap
keeps the order of insertion and thus would help to get authors in the order in which they appeared in the original list (based on first appearance)computeIfAbsent()
executes the lambda if there is no value for the given key and adds it to the map, otherwise just returns the existing value- the lambda is used to create a new author with the same trans id and country code so we don't change the original elements
- we add the values of the current author from the list into the unique author from the map - if this is a new copy we'll just add the values to 0