Home > Software design >  How to find duplicate values with counts and total amount of duplicate values in arraylist
How to find duplicate values with counts and total amount of duplicate values in arraylist

Time:10-21

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:

  1. Split each character string into a name and a value.
  2. Collect statistics on each character string. Sum up and count the characters with the same name.
  3. Store the result in the map.
  4. 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).

  • Related