1

So I have a text file that contains a bunch of strings that I import into the program and what my program does is look for the first index of the first duplicate string:

static final int NOT_FOUND = -1;
dupeIndex = indexOfFirstDupe( wordList, wordCount );
    if ( dupeIndex == NOT_FOUND )
        System.out.format("No duplicate values found in wordList\n");
    else
        System.out.format("First duplicate value in wordList found at index %d\n",dupeIndex);

and the method I use to find the first index of the duplicate is as follows:

static int indexOfFirstDupe( String[] arr, int count )
{       

    Arrays.sort(arr);
    int size = arr.length;
    int index = NOT_FOUND;

    for (int x = 0; x < size; x++) {
        for (int y = x + 1; y < size; y++) {
            if (arr[x].equals(arr[y])) {
                index = x;
                break;
            }
        }
    }
    return index;

The problem is that I get this error:

enter image description here

It's a NullPointerException and from my understanding it means that there's basically a null value(s) in my array of strings(?). Is there any simple solution to this that I am missing? Possibly rewording my method?

Shivam Kumar
  • 1,892
  • 2
  • 21
  • 33
noob4lyfe
  • 53
  • 4
  • Ok, this error should not appear. What are the input values for your string array? – Johannes Kuhn Oct 06 '18 at 03:27
  • Have you tried debugging this code? Or printing out your array? Are there nulls?? – OneCricketeer Oct 06 '18 at 03:50
  • 1
    Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) –  Oct 06 '18 at 04:41
  • you can just use filter `not null`: `arr = Stream.of(arr).filter(x -> x != null).toArray(String[]::new);` – Mikhail Ionkin Oct 06 '18 at 07:26

3 Answers3

0

Assuming that you are correct in your diagnosis

... it means that there's basically a null value(s) in my array of strings ...

... I can think of two workarounds.

  1. Get rid of the null references in the array. Remove them entirely, or replace them with (say) "" or "null" or something else harmless.

  2. There is an overload of the Arrays.sort method that takes a second argument: a Comparator. So what you could do is to implement a Comparator that can handle null without throwing an NPE. (For example, it could treat null as smaller than all non-null strings.)

Here's an example comparator that deals with null:

    public class NullSafeStringComparator implements Comparator<String> {
        public int compare(String s1, String s2) {
            if (s1 == s2) {
                return 0;
            } else if (s1 == null) {
                return -1;
            } else if (s2 == null) {
                return 1;
            } else {
                return s1.compareTo(s2);
            }
        }
    }

Alternatively, for Java 8 and later you can build one as follows:

    Comparator.nullsFirst(Comparator.naturalOrder())            
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

The error is caused by Array.sort(arr);

According to Java doc (https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#sort-java.lang.Object%3aA-):

Sorts the specified array of objects into ascending order, according to the natural ordering of its elements. All elements in the array must implement the Comparable interface.

It is very likely that the exception was thrown when the sort tries to call the compareTo method on the null objects of the String array.

So one simple direct solution is to make sure no null objects in your String array...

wenzi
  • 119
  • 1
  • 6
  • I would guess the null pointer exception was thrown when the java tries to call the compareTo method on the null objects in the String array... – wenzi Oct 06 '18 at 04:06
0

There is a better way to do what you want to do. This is complexity O(n) vs yours is O(n^2) + failing sort.

  public int indexOfFirstDup(String[] arr) {
    Set<String> valuesFound = new HashSet<>();
    for (int i=0;i<arr.length; i++) {
      String s = arr[i];
      // ignore nulls
      if (s == null) { continue; }
      if (valuesFound.contains(s)) {
        // here we identified a duplication and we can leave 
        return i;
      } else {
        valuesFound.add(s);
      }
    }
    // no dups
    return -1;
   }

NOTE the code has not been compiled nor tested - its just an idea!

Deian
  • 1,237
  • 15
  • 31
  • @cricket_007 yes, you're correct to ask that, I need only a boolean but like that I can easily find all duplicates if I should need them. btw thanks for the fix :) – Deian Oct 06 '18 at 03:51
  • if you use int, java will box it into Integer. and incrementing an Integer costs you new instance - this is expensive. Incrementing an element of int[] is at no cost. Again - this makes sense only if I look for all dups so collect full statistics. He is asking for the first only thus we return; – Deian Oct 06 '18 at 03:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/181378/discussion-between-deian-and-cricket-007). – Deian Oct 06 '18 at 04:18
  • I can see that this is a somewhat generic solution, but in this very case a Set is enough instead of Map. – Selindek Oct 06 '18 at 14:28
  • And you are correct in your assessment, Set would do fine and will be faster - let me fix it – Deian Oct 06 '18 at 14:30