从java集合中删除重复元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20626312/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:12:36  来源:igfitidea点击:

Remove duplicate element from the set in java

javaset

提问by Manan Shah

I have set of string array and i want to remove duplicate elements from this...

我有一组字符串数组,我想从中删除重复的元素...

    String[] arr1 = {"a1","b1"};
    String[] arr2 = {"a2","b2"};
    Set<String[]> mySet = new HashSet<String[]>();
    mySet.add(arr1);
    mySet.add(arr2);
    mySet.add(new String[] {"a1","b1"});
    System.out.print(mySet.size());

Currently mySet looks like this:

目前 mySet 看起来像这样:

[{"a1","b1"},{"a2","b2"},{"a1","b1"}]

But I want like this:

但我想要这样:

[{"a1","b1"},{"a2","b2"}]

I know some ways...

我知道一些方法...

  1. Every time I need to run inner loop and check whether its duplicate or not.
  2. Can I override the set's behavior? (hashcode or equals)? ( i do not know how....)
  3. Do I need to change data structure for this? (linkedhashset or list or any other suitable data structure for this?)
  1. 每次我需要运行内循环并检查它是否重复时。
  2. 我可以覆盖集合的行为吗?(哈希码或等于)?( 我不知道怎么....)
  3. 我需要为此更改数据结构吗?(linkedhashset 或 list 或任何其他合适的数据结构?)

采纳答案by c.P.u1

Arrays inherit from Object and don't override the hashCodeand equalsmethods. A HashSetuses a Mapimplementation, which in turn, uses hashCodeand equalsto avoid duplicate elements.

数组继承自 Object 并且不覆盖hashCodeequals方法。AHashSet使用一个Map实现,该实现反过来使用hashCodeequals避免重复元素。

You can use a TreeSetwith a custom Comparatorthat compares the Stringarrays for equality.

您可以将 aTreeSetComparator比较String数组的相等性的自定义一起使用。

Set<String[]> mySet = new TreeSet<>(new Comparator<String[]>() {

  @Override
  public int compare(String[] o1, String[] o2) {
    return Arrays.equals(o1, o2)? 0 : Arrays.hashCode(o1) - Arrays.hashCode(o2);
  }

});

Note that this will only neglect duplicate arrays with the same corresponding elements. If the order of elements is different, it won't be considered as a duplicate.

请注意,这只会忽略具有相同对应元素的重复数组。如果元素的顺序不同,则不会被视为重复。

If you want to be able to discard unorderedduplicates, for e.g., {a1, b1}and {b1, a1}, use this:

如果您希望能够丢弃无序的重复项,例如,{a1, b1}and {b1, a1},请使用以下命令:

@Override
public int compare(String[] o1, String[] o2) {
    int comparedHash = o1.hashCode() - o2.hashCode();
    if(o1.length != o2.length) return comparedHash;
    List<String> list = Arrays.asList(o1);
    for(String s : o2) {
        if(!list.contains(s)) return comparedHash;
    }
    return 0;
}

回答by bcorso

The arrayhashcode is independent of the contents of the array(it inherits the Objecthashcode, which uses the array's reference).

所述array散列码是独立的的内容array(它继承的Object哈希码,它使用阵列的参照)。

However, Listwould do what you want. It uses a hashcode based on the elements in the List. From Java Docs:

但是,List会做你想做的。它使用基于List. 来自 Java 文档

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());


Example:

例子:

List<String> list1 = Arrays.asList("a1","b1");
List<String> list2 = Arrays.asList("a2","b2");
Set<List<String>> mySet = new HashSet<List<String>>();
mySet.add(list1);
mySet.add(list2);
mySet.add(Arrays.asList("a1","b1"));   // duplicate won't be added
System.out.print(mySet.size());        // size = 2

回答by 75inchpianist

Why not use a List implementation? The list.equals will compare elements in each list and determine equality.

为什么不使用 List 实现?list.equals 将比较每个列表中的元素并确定相等性。

List<String> arr1 = new ArrayList<String>();
arr1.add("a1");
arr1.add("b1");
List<String> arr2 = new ArrayList<String>();
arr2.add("a2");
arr2.add("b2");
Set<List<String>> mySet = new HashSet<List<String>>();
mySet.add(arr1);
mySet.add(arr2);

List<String> arr3 = new ArrayList<String>();
arr3.add("a1");
arr3.add("b1");
mySet.add(arr3);
System.out.print(mySet.size());

You suggest overriding equals and hashcode methods. HashSet is backed by a hashmap that uses the hashcode function as its key. So actually you need to override hashcode to represent your equals criteria.

您建议覆盖 equals 和 hashcode 方法。HashSet 由使用 hashcode 函数作为其键的 hashmap 支持。所以实际上你需要覆盖哈希码来表示你的等于标准。

One problem with this. I believe String and therefore String [] are declared as final, so you can't extend them :(

一个问题。我相信 String 和 String [] 被声明为 final,所以你不能扩展它们:(

回答by TheLostMind

Try something like this...

尝试这样的事情......

public static void main(String... args) {
        String[] arr1 = {"a1","b1"};
        String[] arr2 = {"a2","b2"};
        Set<String[]> mySet = new HashSet<String[]>();
        mySet.add(arr1);
        mySet.add(arr2);
        String str[] =new String[] {"a1","b1"}; 
        long t1 = System.nanoTime();
        boolean b =checkContains(str,mySet);
        long t2=System.nanoTime();
        long t = t2-t1;
        System.out.println("time taken : " + t );
        System.out.println(b);

        if(!b)
        {
            mySet.add(str);

        }


    }

    public static boolean checkContains(String[] str, Set mySet)
    {  
        Iterator it = mySet.iterator();
        while(it.hasNext())
        {
            String[] arr = (String[])it.next();
            if(arr[0].equals(str[0]) && arr[1].equals(str[1]) )
            {
                return true;
            }
        }


         return false;
    }

OP :

操作:

time taken : 184306

true

所用时间:184306

真的

回答by Satheesh Cheveri

Arrays uses identity-based Object.hashCode()implementation and there is no easy way to check if they are equal. If it all you still want to go ahead with your problem I would suggest you to use TreeSetwith Comparator

数组使用identity-based Object.hashCode()实现并且没有简单的方法来检查它们是否相等。如果您仍然想继续解决您的问题,我建议您使用 TreeSetComparator

Though not fail proof approach, but you should be able to build fine tuned solution out of my example,

虽然不是防故障方法,但您应该能够从我的示例中构建微调的解决方案,

public static void main(String[] args) {
          String[] arr1 = {"a1","b1"};
            String[] arr2 = {"a2","b2"};
            Set<String[]> mySet = new TreeSet<String[]>(new ArrayComparator());
            mySet.add(arr1);
            mySet.add(arr2);
            mySet.add(new String[] {"a1","b1"});
            System.out.println(mySet.size());
            for(String[] aa: mySet){
                System.out.println(aa[0]+" , "+aa[1]);
            }
    }
}

 class ArrayComparator implements Comparator {

    @Override
    public int compare(Object o1, Object o2) {
        String[] ar1 =(String[]) o1;
        String[] ar2 =(String[]) o2;
        if(ar1.length!=ar2.length){
            return -1;
        }
        for(int count=0;count<ar1.length;count++){
            if(!ar1[count].equals(ar2[count])){
                return -1;
            }
        }
        return 0;
    }

回答by Alpesh Jikadra

Here instead of keeping Set you can use Set<SomeClass> and the override the hash and equals method for the class SomeClass so it will solve your problem.

在这里,您可以使用 Set< SomeClass> 并覆盖 SomeClass 类的哈希和 equals 方法,而不是保留 Set,这样就可以解决您的问题。

回答by Pankaj Goyal

instead of taking array of string you can create a class Like this..

您可以创建一个类,而不是使用字符串数组,就像这样..

public class String1 implements Comparable<String1>{

String str1;
String str2;

public String1(String a, String b) {
    str1 = a;
    str2 = b;
}

public String getStr1() {
    return str1;
}
}

public String getStr2() {
    return str2;
}

@Override
public String toString() {
    return "String1 [str1=" + str1 + ", str2=" + str2
            + "]";
}

@Override
public int compareTo(String1 o) {
    if(str1.contentEquals(o.getStr1()) && str2.contentEquals(o.getStr2()))  return 0 ; 
    return 1;

}


}

And after that insteed of string you can take this one class object. replace HashSet with TreeSet. Like this .

在那之后,你可以使用这个单一的类对象。用 TreeSet 替换 HashSet。像这样 。

     String1 arr1 =new String1("a1","b1");
     String1 arr2 =new String1("a2","b2");
     Set<String1> mySet = new TreeSet<String1>();
     mySet.add(arr1);
     mySet.add(arr2);
     mySet.add(new String1("a1","b1"));
     System.out.print(mySet.size());
     System.out.println(mySet.toString());

So this will sort as well this will check for duplicate also.

所以这也会排序,这也会检查重复项。

回答by Ravi Parsania

try to this code.............

试试这个代码…………

import java.util.HashSet;
import java.util.Set;

public class setDemo {
static Set<String[]> mySet = new HashSet<String[]>();
static Set tempSet = new HashSet();
public static void main(String[] args) {

      String[] arr1 = {"a1","b1"};
      String[] arr2 = {"a2","b2"};

        addObject(arr1);
        addObject(arr2);
        addObject(new String[] {"a1","b1"});
        System.out.print(mySet.size());
       // System.out.println(tempSet);
}
public static void addObject(String[] o){
    StringBuffer sb = new StringBuffer();
    for(Object obj:o){
        sb.append(obj.toString());
    }
    if(!tempSet.contains(sb.toString())){
        tempSet.add(sb.toString());
        mySet.add(o);
    }
}
}