set,HashMap,List重复初步探索


Set:
Set<String> set = new HashSet<String>();
set.add("a");
set.add("b");
set.add("b");
set.add("a");
System.out.println("set.size = " + set.size());
for (Iterator<String> it = set.iterator(); it.hasNext ();) {
String str = (String) it.next();
System.out.println("str=" + str);
}

结果:
set.size = 2
str=b
str=a
  
HashMap:
Map<String,String> map = new HashMap<String,String>();
map.put("a", "1");
map.put("b", "2)");
map.put("a", "3");
map.put("b", "4");
for(Iterator<String> it = map.keySet().iterator(); it.hasNext();) {
String key = (String)it.next();
String value = (String)map.get(key);
System.out.println("key = " + key + " value = " + value);
}

结果:
key = b value = 4
key = a value = 3


 
List:
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("b");
list.add("a");
for(int i = 0; i < list.size(); i++) {
System.out.println("list[" + i +"] = " + list.get(i));
}

结果:
list[0] = a
list[1] = b
list[2] = b
list[3] = a

由此得出结论,只有List是可以有重复元素的,Map以及Set都不可以有重复元素。
欢迎讨论指正。
另附一篇引用文章如下:
关于hashCode与equals方法的说明:

1)对于一个程序的一次执行过程中,同一个对象的hashCode计算的结果一定相同,但是对于同一个程序的不同执行过程中,不要求其hashCode一定相同。

2)对于两个对象,如果使用equals方法比较,结果为true,那么这两个对象的hashCode值一定相同

3)对于两个对象,如果使用equals方法比较,结果为false,那么这两个对象的hashCode值不要求一定不同(但是如果不同可以提高程序性能)



当我们向HashSet中add对象,它首先调用它的HashCode方法,得到这个HashCode的返回整数值,这个整数值就会映射到set里面的某一个位置。如果这个对象里没有对象存在,就把这个对象直接放发哦set里面;如果这个位置已经有对象存在了,这个时候就用equals方法比较这两个方法,如果比较结果相同,就不进行插入。比如下面问题



Set set = new HashSet();

set.add("zhangsan");

set.add("lisi");

set.add("wangwu");

set.add("zhangsan");

这个最后一个set.add("zhangsan");是无法插入成功的,因为String重写了Object的equlas和HashCode方法,按照String的HashCode方法,相同的字符串的HashCode一定是一样的

下面详细分析最后一个set.add("zhangsan")具体插入过程

1.首先根据"zhangsan"调用HashCode方法,获得一个返回值

2.Set根据这个返回值获得一个位置

3.查找这个位置上是否有对象,结果发现有一个对象。值也是“zhangsan”

4.对两个对象调用equals方法,由于String重写了equals方法,这个方法返回true。

所以最后插入失败。



再看下面这个例子

People p1 = new People("zhangsan");

People p2 = new People("lisi");

People p3 = new People("wangwu");

People p4 = new People("zhangsan");

People p5 = new People("zhangsan");



set.add(p1);

set.add(p2);

set.add(p3);

set.add(p4);

set.add(p5);



由于People 继承自Object类,且没有重写equals和HashCode方法,而object的HashCode方法每个不同对象的返回值都是不同的,所以第一步查找插入位置的时候各个对象的位置就不一样,所以一定可以插入进去。



Object类的HashCode实际上根据对象的地址生成的,所以不同对象的HashCode必然不一样,但是String的HashCode是根据字符串的内容和大小生成的,所以相同字符串的HashCode是一样的。





HashSet和HashMap

1. HashSet底层采用HashMap实现

HashMap内部是无序的,取出的顺序和放入的顺序没有关系。java提供了TreeMap是有序的。



2. 这个HashMap的key就是放进HashSet中的对象,而value就是一个Object类型的对象,这个value我们不关心它到底是什么,事实上这是一个随意生成的object对象。



3. 当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该行的key就是向HashSet中增加的那个对象,该行的value就是一个Object类型的常量



4. HashMap底层采用数组维护,这个数组中每个元素实际上又是一个单链表,拥有相同HashCode值的key对应的键值对就放在这个单链表中。

当调用add方法,首先根据这个key的HashCode方法算出一个int值,这个int对应到数组的一个位置,由于可能会有不同的key有相同的HashCode值,所以这个位置上存放的是一个链表。然后这个新加进来的key会和这个链表中的每个元素的key调用equals方法进行比较。如果返回true,就用这个新的键值对替换掉链表中原来那个老的键值对。如果找到最后都没有返回true,就把这个新的键值对添加到链表的头。(之所以不添加到链表的尾是为了提高检索效率,新添加的数据被检索的可能性要高。)



5. 调用增加的那个对象的hashCode方法,来得到一个hashCode值,然后根据该值计算出一个数组的下表索引(计算出数组中的一个位置)



6. 将准备增加到Map中的对象与该位置上的对象进行比较(equals方法),如果相同,那么就将该位置上的那个对象(Entry类型)的value值替换掉;否则,沿着该Entry的链继续重复上述过程,如果到链的最后依然没有找到与此对象相同的对象,那么这个时候就会将该对象增加到数组中,然后将数组中该位置上的那个对象链到这个新对象的后面。



7. 对于HashSet,HashMap来说,这样做的原因就是为了提高查找的速度,使得查找时间不随Set或者Map的大小而改变。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值