我有一组字符串数组,我想删除此中的重复元素...
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());
目前mySet看起来像这样:
[{"a1","b1"},{"a2","b2"},{"a1","b1"}]
但我想这样:
[{"a1","b1"},{"a2","b2"}]
我知道某些方法......
答案 0 :(得分:11)
数组继承自Object,不会覆盖hashCode
和equals
方法。 HashSet
使用Map
实施,后者又使用hashCode
和equals
来避免重复元素。
您可以将TreeSet
与自定义Comparator
一起使用,以便将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);
}
});
请注意,这只会忽略具有相同对应元素的重复数组。如果元素的顺序不同,则不会将其视为重复。
如果您希望能够丢弃无序重复项,例如{a1, b1}
和{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;
}
答案 1 :(得分:10)
array
哈希码独立于array
的内容(它继承了使用数组引用的Object
哈希码。)
然而,List
会做你想要的。它使用基于List
中元素的哈希码。 From Java Docs:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
示例:强>
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
答案 2 :(得分:3)
Arrays使用identity-based Object.hashCode()
实现,没有简单的方法来检查它们是否相等。如果您还想继续解决问题,我建议您使用TreeSet
与比较器
虽然不是故障证明方法,但你应该能够从我的例子中构建精细调整的解决方案,
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;
}
答案 3 :(得分:2)
为什么不使用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());
您建议覆盖equals和hashcode方法。 HashSet由使用哈希码函数作为其键的哈希映射支持。实际上,您需要覆盖哈希码来表示您的等于标准。
这个问题。我相信String和String []被声明为final,所以你不能扩展它们:(
答案 4 :(得分:2)
而不是采用字符串数组,你可以创建一个像这样的类..
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;
}
}
在输入字符串之后,您可以使用这个类对象。 用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());
所以这也将排序,这也将检查重复。
答案 5 :(得分:2)
尝试此代码.............
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);
}
}
}
答案 6 :(得分:1)
尝试这样的事情......
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:
所用时间:184306
真
答案 7 :(得分:1)
此处不使用Set,您可以使用Set&lt; SomeClass &gt;并覆盖SomeClass类的hash和equals方法,因此它将解决您的问题。