首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

问一个 基础有关问题Set m = new HashSet(ls)

2011-12-26 
问一个 基础问题Set m new HashSet(ls)去掉重复数据,下面有两种写法:1.ListlsnewArrayList()ls.add(n

问一个 基础问题Set m = new HashSet(ls);
去掉重复数据,下面有两种写法:
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[]类型的对象就不好用了。有谁知道是什么原因,请告知,谢谢!

[解决办法]
Set中是采用equals来比较两个元素是否相同的。

String strA = new String( "a ");
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中添加时,认为这两个元素不同。
[解决办法]
String 与 String[] 当然不同。
前者,只是一种普通数据类型,比较的是其存储的字串内容。
后者,是数组对象,比较时是比较这些数组对象是否是同一个数组对象,而你用两次new String[]出来的数组对象肯定是不同的数组对象,所以被认为没有重复(地址)的数组对象。
[解决办法]
数组尽管也是对象,不过跟一般的不同,没法override equals和hashCode方法,所以楼主的需求是达不到的
楼主既然用容器了,就不要再用数组了,不觉得矛盾吗?
还有,既然用到了HashSet,还要考虑覆盖hashCode方法,光equals还不够
[解决办法]
如果一个数组作为一个单元的,不妨自己封装一个类,equals和hashCode方法override一下,也很方便的
[解决办法]
比较数组元素是否相等用Arrays.equals(array1,array2);

数组本身.equals(另一个数组)=false;
[解决办法]
是写个类来代替你原本String[]的功能,比如
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;
}
}
[解决办法]
然后你HashSet里存储的就是Unit的instances
[解决办法]
ls.add(new String[] { "aa ", "bb "});
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 "});
结果是什么?
[解决办法]
在JAVA里面数组也是做为引用来处理的..
而在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

希望能够对你有点帮助...

热点排行