【问题标题】:java - best way to store unique list of string arrayjava - 存储字符串数组唯一列表的最佳方法
【发布时间】:2023-03-17 04:20:02
【问题描述】:

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

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

示例字符串数组值:

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

我分别从 JSON 元素中获取 "error message 1""fail" 字符串,并将它们添加到 String 数组对象。现在我想要这个数组的独特组合。所以,如果我有上述 4 个数组,我希望只有三个唯一条目的列表。

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

我将这些字符串数组添加到 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 相关问题的答案中,我了解到,如果需要,必须覆盖 hashcodeequal 方法。但是,如果那是我所缺少的,我不确定在我的情况下我该怎么做?

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

问候,

鲁米特

【问题讨论】:

  • 必须是 String[] 吗? ,能不能把String[]转换成POJO,然后实现.equals.?
  • 我会使用接受 String[] 的 openCSV 库将这些唯一条目写入 CSV 文件。

标签: java arrays string collections


【解决方案1】:

您可以使用Lists 代替数组。如果您使用 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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 为什么叫“key”?不能有两对具有相同的密钥吗?
    【解决方案3】:

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

    【讨论】:

    • 我不能选择地图,因为唯一性必须与“错误消息”和“结果”相结合。所以在这里,我的键是两个字符串的组合。
    【解决方案4】:

    不要使用Set&lt;String[]&gt;,而是创建一个新类,例如:

    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&lt;MyError&gt;。所以,当你这样做时:

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

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

    【讨论】:

      猜你喜欢
      • 2016-01-03
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      • 2020-07-10
      • 2012-04-25
      • 1970-01-01
      相关资源
      最近更新 更多