1

I have a list [0, 0, 1, 0, 1, 2, 0, 2, 3] and I want to find a way to generate an error if a number is repeated in the list.

So, I know that Collections.frequency can count how many time a number is found in a list.

if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(0)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(0) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(1)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(1) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(2)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(2) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(3)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(3) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(4)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(4) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(5)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(5) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(6)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(6) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(7)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(7) + " apparaît plus d'une fois sur la ligne 1");
if (Collections.frequency((Collection<?>) smallerLists.toArray()[0], ((ArrayList<Integer>) smallerLists.toArray()[0]).get(8)) > 1) ;
System.out.println("ERREUR : Le nombre " + ((ArrayList<Integer>) smallerLists.toArray()[0]).get(8) + " apparaît plus d'une fois sur la ligne 1");

I know this code is heavy and I'm sure there's an easier way to do it (an iteration maybe? I'm still very new at programming). The easier way would be to generate an exception by making a constructor but I'm stuck.. Thanks !

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
Natacha BK
  • 137
  • 1
  • 8
  • Does this answer your question? [Java 8, Streams to find the duplicate elements](https://stackoverflow.com/questions/27677256/java-8-streams-to-find-the-duplicate-elements) – RamPrakash Jan 20 '20 at 21:04
  • 1
    So you have a collection of lists? Why don’t you extract `smallerLists.toArray()[0]` into a local variable of right type instead of repeating it, together with a type cast, 27 times? By the way, `smallerLists.iterator().next()` is way more efficient than dumping an entire collection into an array, just to get the first element. And checking for duplicates is as easy as `if(new HashSet<>(collection) .size() != collection.size()) System.out.println("there are duplicates");`… – Holger Jan 21 '20 at 11:49

3 Answers3

1

I would say to use Collectors.groupingBy with Collectors.counting() to collect the value with count in Map

Map<String, Long> valueWithCount = list.stream()
        .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));

And then stream the Map to find any value with count greater than 1

boolean result = valueWithCount.entrySet()
                               .stream()
                               .anyMatch(i->i.getKey().equals(10) && i.getValue()>1);

You can combine both into one operation

boolean result = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream().anyMatch(i -> i.getKey().equals(10) && i.getValue() > 1);
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
0

You can find the duplicates by using one of the solutions suggested in already asked questions like Identify duplicates in a List .

Then, if a duplicate is found, you could pass the result to your exception constructor where you build your message. Then throw your exception.

lugiorgi
  • 473
  • 1
  • 4
  • 12
0

Rather than throwing an exception you could handle dupes with a callback. This way you could deal with multiple exceptions in a list. The solution below uses a new class with a backing TreeMap along with a callback to handle duplicates either in the original array passed into the constructor or for additional items added with the addItem method.

The code produces the following output:

Constructor: 
We have a dupe: 0 which has occurred 2 times so far
We have a dupe: 0 which has occurred 3 times so far
We have a dupe: 1 which has occurred 2 times so far
We have a dupe: 0 which has occurred 4 times so far
We have a dupe: 2 which has occurred 2 times so far

Add new items: 
Duplicate 4 has had 2 occurrences

Frequency List
    0 appears 4 times
    1 appears 2 times
    2 appears 2 times
    3 appears 1 times
    4 appears 2 times

Note that addItem and the constructor are overloaded to handle a null callback and that the second call to addItem passes in a Lambda expression as the callback.

import java.util.Set;
import java.util.TreeMap;

interface DupeHandler{
    public void handleDupe(Integer dupValue, Integer dupCount);
}

class FrequencyList {
    private TreeMap<Integer, Integer> _tm = new TreeMap<Integer, Integer>();

    public FrequencyList(int[] array){
        this(array, (DupeHandler)null);
    }

    public FrequencyList(int[] array, DupeHandler m){
        for(var i : array){
            addItem(i,m);
        }
    }

    public void addItem(Integer i){
        addItem(i, null);
    }

    public void addItem(Integer key, DupeHandler m){
        Integer count = _tm.get(key);
        if(count==null){
            _tm.put(key, Integer.valueOf(1));
        } else {
            Integer newCount = (Integer.valueOf(count+1));
            _tm.put(key, newCount);
            if(m!=null){
                m.handleDupe(key, newCount);
            }
        }
    }

    public Set<Integer> getUniqueValues(){
        return _tm.keySet();
    }

    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append("\nFrequency List\n");
        for(var k:_tm.keySet()){
            sb.append("\t" + k.toString() + " appears " + _tm.get(k).toString()+ " times\n");
        }
        return sb.toString();
    }
}

public class FrequencyListTest implements DupeHandler{
    public static void main(String[] args) {
        int[] intArray = new int[] {0,0,1,0,1,2,0,2,3};
        FrequencyListTest flt = new FrequencyListTest();

        System.out.println("Constructor: ");
        FrequencyList fl = new FrequencyList(intArray, flt);

        System.out.println("\nAdd new items: ");
        fl.addItem(4,flt);
        // callback can also be passed in as a lambda expression
        fl.addItem(4,(n,c)-> 
            System.out.println("Duplicate " + n + " has had " + c + " occurrences"));

        System.out.println(fl);

    }

    @Override
    public void handleDupe(Integer dupValue, Integer dupCount) {
        System.out.println("We have a dupe: " + dupValue + " which has occurred " + dupCount + " times so far");
    }
}

Rex
  • 46
  • 2