2

I have the list of string arrays which may have duplicate entries. I want to get the unique list from these values.

I have a list of string arrays with each array having two String values.

Sample string array values:

{"error message 1", "fail"}
{"error message 2", "N/A"}
{"error message 1", "fail"} // duplicate
{"error message 2", "fail"}

I get the "error message 1" and "fail" strings from JSON elements individually and I add them to a String array object. Now I want the unique combination of this array. So, if I had the above 4 arrays, I want to have the list of only three unique entries.

From the internet search, I drilled down to use the HashSet for my use case (The order does not matter). However, the HashSet adds all 4 entries to the set. I even tried to use the 'contains' to check if the object already exists, but that did not work either. I believe, this is because the contains method is comparing the 'reference' and not the 'value'. Is this the reason that the HashSet is adding duplicate values?

My code to add these String arrays to HashSet is

Set<String[]> uniqueSet = new HashSet<String[]>();
if(!uniqueSet.contains(new String[] {errorMessage,result})) // I get errorMessage and result as separate Strings
   uniqueSet.add(new String[] {errorMessage,result}); // I expect to have only 3 values here in the uniqueSet. But it adds all 4.

From answers for related questions on SO, I understand that hashcode and equal methods have to be overwritten if needed. But, I'm not sure how would I do that in my case if that is what I'm missing?

Also, let me know if you have any other suggestions to better store String arrays uniquely.

Regards,

Rumit

2
  • does it have to be a String[] ? , can you convert String[] into a POJO and then implement .equals.? Commented Jul 1, 2014 at 23:03
  • I would write these unique entries to a CSV file using openCSV library which accepts String[]. Commented Jul 1, 2014 at 23:06

4 Answers 4

7

You could use Lists instead of arrays. If you use the lists from the java.util package, they should already implement hashCode() and equals(Object) in a way that fits your needs (deep equals and deep hasCode):

String[][] stringArrays = new String[][] {
    {"error message 1", "fail"},
    {"error message 2", "N/A"},
    {"error message 1", "fail"}, // duplicate
    {"error message 2", "fail"}
};

Set<List<String>> uniqueSet = new HashSet<List<String>>();
for (String[] a : stringLists) {
    uniqueSet.add(Arrays.asList(a));
}
// uniqueSet.size() should return 3 here
Sign up to request clarification or add additional context in comments.

Comments

1

Since Java does not have tuples, one way to solve it would be using a tuple -

class Pair<L,R> {

    private final L left;
    private final R right;


    Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    L getLeft() {
        return left;
    }

    R getRight() {
        return right;
    }

    @Override
    public int hashCode() { return left.hashCode() ^ right.hashCode(); }

    @Override
    public boolean equals(Object o) {
        if (o == null) return false;
        if (!(o instanceof Pair)) return false;
        Pair pairo = (Pair) o;
        return this.left.equals(pairo.getLeft()) &&
                this.right.equals(pairo.getRight());
    }

}

1 Comment

Why the name "key"? Can't one have two Pairs with the same key?
0

I don't know if it suits your needs, but (at least) a faster solution would be using a HashMap.

HashMap<String, String> hashMap = new HashMap<String, String>();

hashMap.put("error message 1","fail");
hashMap.put("error message 2","fail");
hashMap.put("error message 1","N/A");

The result would be only two elements in the list as the Key element (in this case "error message 1") will be overwritten with the next one you put into the list.

Result:

hashMap=[{"error message 1","N/A"},{"error message 2","fail"}];

1 Comment

I cannot go for the Map as the uniqueness has to be combined with 'errormessage' and 'result. So here, my key is a combination of two Strings.
0

Instead of using Set<String[]>, create a new class, for example:

public class MyError {
    private String message;
    private String detail;

    //constructors, getters and setters

    public boolean equals(Object other) {
        //implement equals here - i suggest you to use an IDE auto generated equals()
    }
}

And use Set<MyError>. So, when you do:

uniqueSet.add(new MyError(errorMessage, result));

it will suppress the duplicated entries correctly due to the equals implementation.

Comments

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.