去掉重复数据,下面有两种写法:
1. List ls = new ArrayList();
ls.add(new String("a"));
ls.add(new String("a"));
Set m = new HashSet(ls);
System.out.println(m.size());2. List ls = new ArrayList();
ls.add(new String[] {"aa", "bb"});
ls.add(new String[] {"aa", "bb"});
Set m = new HashSet(ls);
System.out.println(m.size());
运行后可以看到程序1输出的是1,而程序2输出的却是2。
本意是想用Set m = new HashSet(ls);去掉重复数据的,没想到碰到String[]类型的对象就不好用了。有谁知道是什么原因,请告知,谢谢!
1. List ls = new ArrayList();
ls.add(new String("a"));
ls.add(new String("a"));
Set m = new HashSet(ls);
System.out.println(m.size());2. List ls = new ArrayList();
ls.add(new String[] {"aa", "bb"});
ls.add(new String[] {"aa", "bb"});
Set m = new HashSet(ls);
System.out.println(m.size());
运行后可以看到程序1输出的是1,而程序2输出的却是2。
本意是想用Set m = new HashSet(ls);去掉重复数据的,没想到碰到String[]类型的对象就不好用了。有谁知道是什么原因,请告知,谢谢!
String strB = new String("a");
那么strA.equals(strB)返回的结果是true。在向Set中添加时,认为这两个元素相同。String[] arrA = new String[]{"aa","bb"};
String[] arrB = new String[]{"aa","bb"};
那么arrA.equals(arrB)返回false。在向Set中添加时,认为这两个元素不同。
前者,只是一种普通数据类型,比较的是其存储的字串内容。
后者,是数组对象,比较时是比较这些数组对象是否是同一个数组对象,而你用两次new String[]出来的数组对象肯定是不同的数组对象,所以被认为没有重复(地址)的数组对象。
楼主既然用容器了,就不要再用数组了,不觉得矛盾吗?
还有,既然用到了HashSet,还要考虑覆盖hashCode方法,光equals还不够
我觉得你说的用词 不恰当啊。String 当然是对象,而你说的“普通数据类型”好像这个概念可以理解成“基本数据类型”那当然不是对象了,如果你说的是别的什么东东在下就不知道了。至于你说的“后者,是数组对象,比较时是比较这些数组对象是否是同一个数组对象,而你用两次new String[]出来的数组对象肯定是不同的数组对象,所以被认为没有重复(地址)的数组对象。”我就更不敢苟同了,equals比较得是 对象的内容,和地址没有任何关系,你就是 new 一百个String("abc"),他们也是不同的对象,但是用equals比较的结果是true.
个人意见,呵呵。
如果一个数组作为一个单元的,不妨自己封装一个类,equals和hashCode方法override一下,也很方便的
------------------------------------------------------------------------------
能否说的详细些?你的意思是说要自己写一个类BHashSet来extendsHashSet吗?然后重写方法equals和hashCode?
class Unit{
private String[]values;
public boolean equals(Object o){
return o instanceof Unit && java.util.Arrays.equals((Unit)o.values, this.values);
}
public int hashCode(){//hashCode的算法可以自己随便定,但是要尽量减少hash值的重复
int hash=0;
for(int i=0; values!=null&&i<values.length; i++)
hash+=values[i].hashCode(); return hash;
}
}
private String[]values;
public boolean equals(Object o){
return o instanceof Unit && java.util.Arrays.equals((Unit)o.values, this.values);
}
public int hashCode(){//hashCode的算法可以自己随便定,但是要尽量减少hash值的重复
int hash=0;
for(int i=0; values!=null&&i<values.length; i++)
hash+=values[i].hashCode(); return hash;
}
}
不太明白你写得这个类我要怎么用?能否细说一下?谢谢!
String[] 对象我只是用来存储数据,然后我要去掉重复的就可以了。
ls.add(new String[] {"aa", "bb"});你这不是把一个String[]作为一个存储单元考虑的吗
我给你的Unit类不是有一个private String[]values的吗,只不过包装了一下楼主如果仍旧是以单个的String为单位的话,即你存储后只是想保留"aa","bb",就别用数组了,如果是这个意思的话,楼主的思想都是错的
你举个例子吧
ls.add(new String[] {"aa", "bb"});
ls.add(new String[] {"aa", "bb"});
结果是什么?
ls.add(new String[] {"aa", "bb"});
ls.add(new String[] {"aa", "bb"});
...
...// todo process ls.remove repeated data我要得到没有重复数据的ls对象.即:这个对象new String[] {"aa", "bb"}在ls 里面有两个,我只想留一个.
最后得到的结果是
ls里面只有一个new String[] {"aa", "bb"}对象.上面只是举个例子,因为List里面有很多数据几千条,都是String[]对象,有很多重复的,对于重复的String[]对象我只想留一个.这次明白了吗?
加个构造方法
public Unit(String[]sa){
this.values = sa;
}ls.add(new Unit(new String[]{"aa","bb"}));//保证Unit的实例的唯一性,即保证String[]的唯一性,因为数组的特殊性,没有重写equals、hashCode方法来保证唯一性,无法实现楼主的需求。拿Unit包装一下String[]来间接实现达到目的。还不懂的话,我就无语了
而在JAVA如果没有在类中实现equals()的方法时,会默认为跟'=='相同,'=='含义应该知道吗?
[摘自JAVA API中的Object equals()方法]
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。所以,你的两个字符串数组并不相等,因为它们的引用并不相同.当经过重写believefym(feng)提示的equals()和hashCode()方法后,可以实现当值相等时,那么euqals()返回true.而楼主的第一个程序,中间的String对象,因为JAVA本身已经重写了equals()和hashCode()方法.如下:[摘自JAVA src.zip中的java/lang/String.java]
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
} public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count; for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}所以,JAVA会自动调用这两个方法,来进行对象的相等比较. 在这其中,要区别的是引用的默认比较规则.看下这篇文章吧!
Java新手入门的30个基本概念[3]
http://community.csdn.net/Expert/topic/5310/5310996.xml?temp=7.429141E-02希望能够对你有点帮助...
"而在JAVA如果没有在类中实现equals()的方法时,会默认为跟'=='相同,'=='含义应该知道吗?"
你说的这句话不对!!equals()和"=="是不一样的,即使不实现equals()方法,你用equals()和"=="也是不一样的!这是相当基础的知识。"=="比较的是地址,equals()比较的是内容。
至于这个"Java新手入门的30个基本概念[3]
http://community.csdn.net/Expert/topic/5310/5310996.xml?temp=7.429141E-02"我想我不用看了。
不过,到是有一个问题真要请教您了,public int hashCode() 这个方法是怎么个用法,您能给讲明白吗?
return (this == obj);
}这个是Object类equals方法的源代码,“这是相当基础的知识。"=="比较的是地址,equals()比较的是内容。”如果你没有override equals方法,谁知道你要比较的是内容,谁知道这个内容是怎么比较的
楼主,基础有待提高
这下我就明白了,当我用Set set = new HashSet(ls);的时候,在构造HashSet时会去调用Unit的equals方法和hashCode方法进行比较,对吧?这样数组对象就相同了。谢谢!!
能否再请教一下,这个hashCode()方法是作什么用的?