Map和Set的操作:增、删、判断、取出。
add和put的不同:
Set是单列集合,添加相同的元素,所以add方法只添加一个进去。Map的put方法如果添加了多个键相同的元素,则会用最后添加的值来覆盖之前的值,而这个键是最先添加的那个,并每天有被覆盖这一说。
凡是遇到hash,hashmap或者hashset,底层数据结构都是哈西表,存储数据的时候一样,都是先判断当前哈西值和已添加元素的哈希值是否相同,如果不相同,就存数据,不然就继续判断equals方法,若返回true就不存,返回false就存。所以元素都要复写一下hashCode()和equals()方法。
注意:判断元素是否存在以及删除操作,依赖于这两个方法,这就是哈希表的特性。(ArrayList只依赖equals方法)
而遇到Tree开头的,TreeSet 和TreeMap,底层都是二叉树,存储数据遵循小的在左大的在右的原则,每个数下面最多只能有两个分支,新添加进去的数据依次往下比。若存的多了,会自动折中查找,所以这种数据结构的效率是比较高的。
Tree类型的查重:
比较器,对于不具有自然顺序的类型,比如一个Student类
(1)让这个类具备可比性
让Student类实现Comparable这个接口,然后重写里面的compareTo()方法,返回值为0是保证唯一性的依据:
(2)让将要添加这个类的对象的集合比如Set,具有可比性
自定义一个比较器MyCompare,实现Comparato这个接口,并把newMyCompare()当作参数传进Set这个类当中。
重写Comparator里面的compare()方法,这个方法里面有两个参数O1和O2,比较这两个对象的toString()值。比如下面:
public int compare(Object o1, Object o2) {
Book b1 = (Book)o1;
Book b2 = (Book)o2;
return b1.getDate().toString().compareTo(b2.getDate().toString());
}
两种比较器,重写的方法都是int类型。所以Tree类型存储数据只看相比的结果:正、负、0。0决定存不存,保证唯一性,正负决定存储的顺序。
注意:在定义student这个类的时候,最好把hashCode()和equals()都重写一下(还有toString(),然后让这个类实现comparable接口或者自定一个比较器。这样一来,student既可以存进hashset里面又可以存进TreeSet里面。
TreeSet的方法:
E ceiling(E e) 返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。
first() 返回此 set 中当前第一个(最低)元素
floor(E e) 返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。
HashMap:
里面存的是键值对,一个键可以对应多个值,但一个值只可以对应一个键。那么hashmap可不可以存空键后面跟一个值?能!
直接返回值。
Map集合没有迭代器,它的取出方式有两种:
第一种是KeySet()方法,把键存进Set集合中,然后用Set集合的迭代器遍历得到所有的键,再用Map集合的get()方法,参数传入键,取出值。
第二种是entrySet()方法,把键值对这种映射关系存进Set集合。调用entry(),返回值实际上包含了键和值两个数据,用getke'y()方法和 getvalue()两个方法,可以分别取出键和值。
TreeMap sets = new TreeMap(new MyCompare());
Set set = sets.entrySet();
Iterator it = set.iterator();
while (it.hasNext()) {
/*加了泛型的话,直接返回string key和string value,
然后用key和value调用getKey()和getValue()方法,不然。就用下面的强转*/
Entry entry = (Entry)it.next();
System.out.println(entry.getKey()+entry.getValue());