2

I have made a pair word detector, which gives me an output of true or false.
If the value in the string array contains the same string letter (duplication) will return true.
I used below code using nested loops
Now, I want to do the same concept without the usage of any loops?
How can I do this, any examples or what type of java collection framework is needed?
Thank you

Main:

public class Main                                       
{                                       
  public static void main(String[] args)                                        
  {                                     
    String[] box = {"Monkey","Lion","Elephant","Zebra","Tiger", "Hippo"};                                       
    String[] box2 = {"Shop","Biscuit","Cake","Cake"};                                       
    String[] box3 = {"Entrance","Gate","Price","Door","Gate"};
    String[] box4 = {"Female","Male"};                                      
    System.out.println(Pairfinder.test(box));        //false                                
    System.out.println(Pairfinder.test(box2));       //true                                 
    System.out.println(Pairfinder.test(box3));       //true  
    System.out.println(Pairfinder.test(box4));       //false                            
  }                                     
}

Sub:

public class Pairfinder                                     
{                                       
  public static boolean test(String[] value)                                        
  {                                     
    for (int i = 0; i < value.length; i++) {                                        
            for (int j = 0; j < value.length; j++) {                                        
                if (value[i].equals(value[j]) && i != j) {                                      
                    return true;                                        
                }                                       
            }                                       
        }                                       
        return false;                                       
    }                                       
}
4
  • Without loops? Do you mean with lambda expression? You have to iterate in some way over the array to find duplicates. Commented Mar 19, 2019 at 22:01
  • 1
    You could try inserting all the items into a Set (which doesn't allow duplicates) - if the set is smaller than the array then you have duplicates. Commented Mar 19, 2019 at 22:03
  • ^ That would work but the Set would be using loops behind the scenes. Commented Mar 19, 2019 at 22:05
  • You can use a stream. Use Arrays.stream and collect them to a map grouped by the value itself. Then do a downstream filter fit those where the count is greater than 1. If the result has at least 1 entry then there was a duplicate. Commented Mar 19, 2019 at 22:07

3 Answers 3

1

Here is simple example for your cause

public static void main(String[] args) {
    String[] box = {"Monkey", "Lion", "Elephant", "Zebra", "Tiger", "Hippo"};
    String[] box2 = {"Shop", "Biscuit", "Cake", "Cake"};
    String[] box3 = {"Entrance", "Gate", "Price", "Door", "Gate"};
    String[] box4 = {"Female", "Male"};
    System.out.println(checkIt(box));        //false                                
    System.out.println(checkIt(box2));       //true                                 
    System.out.println(checkIt(box3));       //true  
    System.out.println(checkIt(box4));           //false   

}

public static boolean checkIt(String[] text) {
    return !Arrays.stream(text).allMatch(new HashSet<>()::add);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Another clever solution that I have to think about :-) I still like the distinct one by @SamuelPhilipp but great to see so many different approaches that all work!
1

You can use Java Streams with a one liner:

public static boolean test(String[] value) {
    return Arrays.stream(value).anyMatch(v -> Collections.frequency(Arrays.asList(value), v) > 1);
}

But that is probably not the most performant solution, because it has a time complexity of O(n²).

Alternatively you can use a distinct():

public static boolean test(String[] value) {
    return Arrays.stream(value).distinct().count() < value.length;
}

If you want to get the duplicate values you can combine both methods:

public static String[] getDuplicates(String[] value) {
    return Arrays.stream(value)
            .filter(v -> Collections.frequency(Arrays.asList(value), v) > 1)
            .distinct()
            .toArray(String[]::new);
}

This version also has a time complexity of O(n²) because of the frequency() count. A better solution would be:

public static String[] getDuplicates(String[] value) {
    return Arrays.stream(value)
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream()
            .filter(e -> e.getValue() > 1)
            .map(Map.Entry::getKey)
            .toArray(String[]::new);
}

4 Comments

The distinct solution is the best one here. The sets (other answers) are clear but the distinct one is just as readable as the sets. The anyMatch version is clever but it makes me have to think ;-)
The anyMatch solution is horrible, as it will search the entire array for each array element, also known as “quadratic time complexity”. The distinct() variant is not bad, but still looks like an overuse of the Stream API, a good old return new HashSet<>(Arrays.asList(value)).size() == value.length; would do too. The getDuplicates variant doing frequency for every element again, will again lead to quadratic time complexity. You can use .collect(groupingBy(Function.identity(),counting())) .entrySet().stream() .filter(e -> e.getValue()>1) .map(e -> e.getKey) .toArray(String[]::new);
Thanks @Holger I already noticed the time complexity with frequency() but I didn't mention it that clear in my answer. I updated it and added the other example for finding the duplicates.
@Holger Oh, just copied it and forgot to remove that part :D Thanks again.
0

Yes, you can do that by using HashSet in time complexity O(n)
The idea is that
Put all items in a HashSet
If the array contains duplicate values
The length of HashSet will not equal the length of array
Because add function of HashSet will add the specified element to this set if it is not already present

public static boolean test(String[] value) {
    Set<String> hashSet = new HashSet<>(Arrays.asList(value));
    return (value.length != hashSet.size());
}

1 Comment

To better hide the loop why not Set<String> set = new HashSet<>(Arrays.asList(value)); ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.