【问题标题】:HashSet adding duplicate StringsHashSet添加重复字符串
【发布时间】:2015-09-04 01:45:43
【问题描述】:

我正在尝试从 android 中的联系人提供程序获取唯一的电话号码,并且我正在使用 HashSet 添加联系人的不同电话号码

   Set<String> newNumbers = new HashSet<>();

   while(findNumbers.moveToNext()){
      String phone = findNumbers.getString(0);
      phone = phone.replaceAll("[\\s\\-()]", ""); 
      boolean isNumberAdded = newNumbers.add(phone);
      if(isNumberAdded){
         Log.d(TAG,"Phone= " + phone);
       }else{
         Log.d(TAG,"Rejected Phone= " + phone);
         continue;
        }
    }

但是会发生这种情况:

  1. 电话= 0502809903
  2. 电话= +971556072980
  3. 拒绝电话= +971556072980
  4. 电话= +971552767944
  5. 电话= +971556072980

编辑: 如果字符串是这样创建的,它可以工作,但是我从光标处得到的字符串不能。

    ArrayList<String> testing = new ArrayList<String>();
    testing.add("0502809903");
    testing.add("+971556072980");
    testing.add("+971556072980");
    testing.add("+971552767944");
    testing.add("+971556072980");

    Set<String> numbers = new HashSet<>();
    for(String data: testing){

        boolean isNumberAdded = numbers.add(data);
        if(isNumberAdded){
            Log.d("Test","Accepted " + data);
        }else{
            Log.d("Test","Rejected " + data);
        }
    }

Edit2:将数字显示为 char 数组,我该如何解决?

  1. 原始 = [0, 5, 0, 2, 8, 0, 9, 9, 0, 3]
  2. 接受电话= 0502809903
  3. 原始 = [, +, 9, 7, 1, 5, 5, 6, 0, 7, 2, 9, 8, 0, ]​​i>
  4. 接受电话= +971556072980
  5. 原始 = [, +, 9, 7, 1, 5, 5, 6, 0, 7, 2, 9, 8, 0, ]​​i>
  6. 拒绝电话= +971556072980
  7. 原始 = [+, 9, 7, 1, 5, 5, 2, 7, 6, 7, 9, 4, 4]
  8. 接受电话= +971552767944
  9. 原始 = [+, 9, 7, 1, 5, 5, 6, 0, 7, 2, 9, 8, 0]
  10. 接受电话= +971556072980

【问题讨论】:

  • 你能告诉我们newNumbers对象的创建吗?我对它有什么类型感兴趣。
  • 你是说第一次添加到集合中的数字被拒绝,第二次添加它被接受?还是第一个被第二个覆盖?
  • 它在 90% 的时间里都有效,这是 10%....
  • 您缺少一些代码。在您当前的代码中,您创建一个 HashSet,向其中添加一个元素,然后代码突然结束。如果没有循环,您就无法在某处获得输出。您应该提供循环代码,因为错误可能不在您发布的代码中,而与您在多次迭代中循环和存储变量的方式有关。
  • 太好了,您已经隔离了问题。光标中的字符串包含示例字符串不包含的内容。更仔细地检查这些字符串,您应该会发现错误。

标签: java android duplicates hashset


【解决方案1】:

你的字符串中有垃圾。 试试这个:

boolean isNumberAdded = newNumbers.add(phone.trim());

这应该可以解决问题。

编辑: 或者也许它没有......根据this question,如果你想删除不可打印的字符,你应该使用以下:

boolean isNumberAdded = newNumbers.add(phone.replaceAll("\\p{C}", ""));

让我知道这次是否有效。

【讨论】:

  • 没有对 char 数组做任何事情,看起来一样
【解决方案2】:

HashSet 将使用 GetHashCode 和 Equals 来确定对象的相等性。现在,由于您没有覆盖这些方法,因此将使用默认的 System.Object 的引用相等。每次添加新值时,它都是唯一的对象实例,因此 HashSet 将其视为唯一对象。

您将需要覆盖哈希码和相等。

Why is it important to override GetHashCode when Equals method is overridden?

【讨论】:

  • 如果设置为false,表示没有添加值对吗?
  • 我必须重写字符串对象...?
  • 你不能覆盖 String 类中的任何东西,它是最终的。这个答案是完全错误的。
  • 答案在概念上是正确的,但是你当然不能覆盖 String 的 equals() 和 hashCode()。只需在内部创建一个带有 String 的 Serializable POJO,覆盖这两个方法即可完成
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多