这几天看了下 HashSet 和 HashMap,谈谈我的理解吧,如果有错误的话,请麻烦指出纠正,谢谢!
1.1 HashSet
1.11 HashSet是实现Set接口的集合类,具备的特点是:
(1)遍历元素时不保证元素返回的顺序
(2)不允许重复元素,这里的“重复”元素指两个对象具有相同的散列码并且用equals()方法比较后返回true
(3)允许包含空元素
(4)底层是哈希表
1.12 HashSet存储元素的原理
以上拆自《Java高级编程》中对HashSet的描述。
(在Set中添加对象时,使用该对象的散列码来选择放置对象的"桶"。不相等的对象可能有不同的散列码但仍放在同一个桶中,而判断为相等的两个对象总是放在同一个桶中。这点极为重要,因为判断Set中是否包含指定对象时,会使用该对象的散列码来判断该对象所在的桶,并遍历该桶中的对象同时使用equals()方法判断该桶是否已经包含该对象。换句话说,用hashcode()方法指定对象所在的对象子集合(桶),然后根据equals()检查该子集合并判断是否找到指定的对象。)
根据我的理解,我用以下文字描述出来,希望我理解没有错误
当往HashSet添加元素的时候,首先会调用元素的hashCode方法得到对象的哈希码值,通过值计算出该元素所在哈希表中的位置
(1)如果算出的位置没有任何值,那么该元素可以添加到哈希表中
(2)如果算出该位置已经存在其他元素,则调用equlas()方法与该位置上的元素比较,如果返回false,则添加进去。
假设有这么几种情况,通过重写HashCode和equlas()试试看
1.hashCode相同且equals()返回为真
public class HashSetDemo { public static void main(String[] args) { HashSet<Person> set=new HashSet(); Person p1=new Person(20, "小瀚", 20); Person p2=new Person(20, "小瀚", 20); set.add(p1); set.add(p2); System.out.println("p1 hashCode="+p1.hashCode()+" "+"p2 hashCode="+p2.hashCode()); System.out.println("Size="+set.size()+ " Set="+set); } } class Person { private int id; private String name; private int age; public Person(int id,String name, int age) { this.id=id; this.name = name; this.age = age; } @Override public int hashCode() { return id; } @Override public boolean equals(Object obj) { Person p=(Person) obj; return name.equals(p.name) && age==p.age; } @Override public String toString(){ return "id="+id+" name="+name+" age="+age; } } 输出结果为: p1 hashCode=20 p2 hashCode=20 Size=1Set=[id=20 name=小瀚 age=20]
2.hashCode相同但equals()返回假
HashSet<Person> set=new HashSet(); Person p1=new Person(20, "小瀚", 20); Person p2=new Person(20, "小露", 20); set.add(p1); set.add(p2); System.out.println("p1 hashCode="+p1.hashCode()+" "+"p2 hashCode="+p2.hashCode()); System.out.println("Size="+set.size()+ " Set="+set); 输出结果为: p1 hashCode=20 p2 hashCode=20 Size=2 Set=[id=20 name=小露 age=20, id=20 name=小瀚 age=20]
由上面结果我们可知,当HashCode()相同的时候,会去调用equlas()方法来比较元素,从而判断是否将元素添加进去
1.2 HashMap
Set是对象的集合,而Map不但是对象的集合,并且每个对象都有一个对应值。也就是说,映射(Map)表示一组键值对,键就是集合中元素。其中HashMap是实现Map接口的一个类,具备的特点是:
(1)线程不安全,存取速度快。底层是以哈希表实现的.
(2)不允许重复元素。
Map<Integer,String> map=new HashMap<Integer,String>(); map.put(1,"小瀚"); map.put(2,"小露"); String s=map.get(3); //这行代码在映射中查找键3,如果有该键,则返回对应的值,如果没有该键,则返回空。这种查找功能极为有用,Map中是根据键查找值无需遍历映射中的键表,而是利用hashCode定位值所在的哈希表的位置,因此即使非常大的Map集合中也能进行快速查找。
下面的代码演示了遍历Map的几种方式
Map<String,String> map=new HashMap<String,String>(); map.put("a", "aa"); map.put("b", "bb"); map.put("c", "cc"); //第一种 entrySet() 返回此映射中包含的映射关系的 Set 视图。 for(Entry<String, String>entry:map.entrySet()){ System.out.println("key="+entry.getKey()+" value="+entry.getValue()); } System.out.println("===========华丽的分割线==============="); //第二种 keySet 返回此映射中包含的键的 Set 视图。 for(String s : map.keySet()){ System.out.println("key="+s+" value="+map.get(s)); } System.out.println("===========华丽的分割线==============="); //第三种 value返回此映射中包含的值的 Collection 视图。 for(String s:map.values()){ System.out.println("value="+s); }
这是我对集合的一点点了解,不对的地方请多多指教!