java - 存储唯一字符串数组列表的最佳方法

时间:2014-07-01 23:00:24

标签: java arrays string collections

我有可能有重复条目的字符串数组列表。我想从这些值中获取唯一的列表。

我有一个字符串数组列表,每个数组都有两个String值。

示例字符串数组值:

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

我单独从JSON元素中获取"错误消息1" "失败" 字符串,然后将其添加到字符串数组对象。现在我想要这个数组的独特组合。所以,如果我有上面的4个数组,我想只列出三个唯一的条目。

从互联网搜索中,我深入研究使用 HashSet 作为我的用例(顺序无关紧要)。但是, HashSet 会将所有4个条目添加到集合中。我甚至尝试使用' 包含'检查对象是否已存在,但这也不起作用。我相信,这是因为contains方法正在比较' 参考'而不是' '。这是 HashSet 添加重复值的原因吗?

我将这些String数组添加到HashSet的代码是

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.

根据有关SO的相关问题的答案,我了解如果需要,必须覆盖哈希码相等方法。但是,我不确定如果那是我错过的,我将如何做到这一点呢?

另外,如果您有任何其他建议可以更好地存储String数组,请告诉我。

此致

Rumit

4 个答案:

答案 0 :(得分:7)

您可以使用List代替数组。如果您使用java.util包中的列表,他们应该已经以适合您需求的方式实现hashCode()equals(Object)(深度等于和深度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

答案 1 :(得分:1)

由于Java没有元组,解决问题的一种方法是使用元组 -

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());
    }

}

答案 2 :(得分:0)

我不知道它是否符合您的需求,但(至少)更快的解决方案是使用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");

结果将只是列表中的两个元素,因为Key元素(在本例中为“错误消息1”)将被您放入列表中的下一个元素覆盖。

结果:

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

答案 3 :(得分:0)

创建一个新类,而不是使用Set<String[]>,例如:

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()
    }
}

并使用Set<MyError>。所以,当你这样做时:

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

由于equals实现,它将正确地抑制重复的条目。