I have list of data with amount, I want to separate duplicate data with that count and that total amount.
ArrayList<String> al=new ArrayList<String>();
al.add("aa-10.00");
al.add("bb-15.00");
al.add("aa-20.00");
al.add("aa-30.00");
al.add("bb-10.00");
Output data amount count
aa 60.00 3
bb 25.00 2
CodePudding user response:
The ideas for dealing with this problem are as follows:
- Split each character string into a name and a value.
- Collect statistics on each character string. Sum up and count the characters with the same name.
- Store the result in the map.
- Print the statistics result.
ArrayList<String> al=new ArrayList<>();
al.add("aa-10.00");
al.add("bb-15.00");
al.add("aa-20.00");
al.add("aa-30.00");
al.add("bb-10.00");
// Map<data name such as "aa", Pair<sum, count> >
Map<String, Pair<Double, Integer>> result = new HashMap<>();
al.forEach(record -> {
// split data by "-", and split aa-10.00 to "aa" and "10.00"
String [] splitRecord = record.split("-");
// if already exsit, sum and cardinality
if (result.containsKey(splitRecord[0])) {
result.put(splitRecord[0], new Pair<>(Double.valueOf(splitRecord[1]) result.get(splitRecord[0]).first(), result.get(splitRecord[0]).second() 1));
} else {
result.put(splitRecord[0], new Pair<>(Double.valueOf(splitRecord[1]), 1));
}
});
System.out.println(result);
CodePudding user response:
Since release of Java 8 back in March 2014, Java provides Stream API which allows group by elements of collections and collect some statistical data.
So, the input strings should be split into parts: name and amount separated with dash -
, grouped by String name, and statistics should be collected for double
amount.
Using Collection::stream
, String::split
, Collectors.groupingBy
(with the Supplier and downstream collector), Collectors.summarizingDouble
returning the DoubleSummaryStatistics
the following solution can be implemented:
List<String> al = Arrays.asList(
"aa-10.00", "bb-15.00", "aa-20.00", "aa-30.00", "bb-10.00"
);
Map<String, DoubleSummaryStatistics> stats = al
.stream()
.map(s -> s.split("-")) // Stream<String[]>
.collect(Collectors.groupingBy(
arr -> arr[0],
LinkedHashMap::new,
Collectors.summarizingDouble(arr -> Double.parseDouble(arr[1]))
));
System.out.println("data amount count");
stats.forEach((name, stat) -> System.out.printf("%4s %6.2f =%n",
name, stat.getSum(), stat.getCount()
));
Output:
data amount count
aa 60.00 3
bb 25.00 2
LinkedHashMap
ensures that the elements appear in the insertion order (as they appeared in the input list).