集合框架复习总结(四)

来源:互联网 发布:前端怎么获取后端数据 编辑:程序博客网 时间:2024/06/06 02:52

之前复习完了List和Set的内容,剩下Map的内容也一起复习了。

Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效


Map是一种把键对象和值对象进行关联的容器
        一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。
        当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求。你可以将任意多个键都映射到一个值对象上,这不会发生任何问题(不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象)。

Map有两种比较常用的实现:HashMap和TreeMap。HashMap也用到了哈希码的算法,以便快速查找一个键,TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。键和值的关联很简单,用put(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。

     一般来说,我们常用的Map子类有HashMap,TreeMap和LinkedHashMap,其与Set的存储结构很相似,LinkedHashMap是底层链表结构,HashMap是运用了哈希算法的,TreeMap是树结构存储,进行了排序。

一、Map基本功能描述
1、添加功能
 V put(K key,V value):添加元素。
 如果键是第一次存储,就直接存储元素,返回null
 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
2、删除功能
 void clear():移除所有的键值对元素
 V remove(Object key):根据键删除键值对元素,并把值返回
3、判断功能
 boolean containsKey(Object key):判断集合是否包含指定的键
 boolean containsValue(Object value):判断集合是否包含指定的值
 boolean isEmpty():判断集合是否为空
4、获取功能
 Set<Map.Entry<K,V>> entrySet():
 V get(Object key):根据键获取值
 Set<K> keySet():获取集合中所有键的集合
 Collection<V> values():获取集合中所有值的集合
5、长度功能
 int size():返回集合中的键值对的个数


下面举一些例子介绍:

例子1:

public static void main(String[] args) {Map<String,Integer> map = new HashMap<String, Integer>();//添加元素map.put("Jack",22);map.put("Marry",23);System.out.println(map);//删除,清空功能map.remove("Jack");System.out.println(map);map.clear();System.out.println(map);}

得到的结果为:

{Jack=22, Marry=23}
{Marry=23}
{}


例子2:

map.put("Jack",22);map.put("Marry",23);System.out.println(map);//判断集合是否包含键System.out.println(map.containsKey("Jack"));System.out.println(map.containsKey("Tom"));//判断集合是否包含指定的值System.out.println(map.containsValue(22));System.out.println(map.containsValue(25));

得出的结果为:
{Jack=22, Marry=23}
true
false
true
false


例子3:

map.put("Jack",22);map.put("Marry",23);System.out.println(map);//判断集合是否为空System.out.println(map.isEmpty());map.clear();System.out.println(map.isEmpty());

得到的结果为:
{Jack=22, Marry=23}
false
true


例子4:

//添加元素map.put("Jack",22);map.put("Marry",23);//得到键获取该键的值System.out.println(map.get("Jack"));System.out.println(map.get("Tom"));//获取集合的长度System.out.println(map.size());


得到的结果为:
22
null
2


下面重点讲一下遍历的方法:
通常可以使用keyset()方法得到每一个key,然后get(key),得到每一个key对应的值这样来遍历:

map.put("Jack",22);map.put("Marry",23);map.put("Tom", 23);System.out.println(map.keySet());for (String key : map.keySet()) {System.out.println("我叫" + key + ",今年" + map.get(key) +"岁");}

得出的结果为:
我叫Jack,今年22岁
我叫Tom,今年23岁
我叫Marry,今年23岁


那么,还有一种方法,是把键和值的键值对封装成一个对象,然后来遍历的:
其方法是使用Map.Entry接口,而Entry接口是Map中的一个子接口,可以单独使用,而还需要获取entrySet()来得到所有键值对,举个例子来解释一下这个方法应该怎么使用:
map.put("Jack",22);map.put("Marry",23);map.put("Tom", 23);System.out.println(map.entrySet());for (Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry + "  我叫" + entry.getKey() + ",年龄为" + entry.getValue());}

得到的结果为:
[Jack=22, Tom=23, Marry=23]
Jack=22  我叫Jack,年龄为22
Tom=23  我叫Tom,年龄为23
Marry=23  我叫Marry,年龄为23


其中包含的方法有entrySet()是获取集合中的键值对,getKey()和getvalue()分别是获取键和值。
当然,我们也可以用迭代器进行遍历。


二、Map接口的子类HashMap,TreeMap和LinkedHashMap的简单介绍
1、HashMap
此类不保证映射的顺序,特别是它不保证该顺序恒久不变。基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。另外,HashMap是非线程安全的,也就是说在多线程的环境下,可能会存在问题,而Hashtable是线程安全的。


重点:HashMap和Hashtable的区别
* Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
* Hashtable不可以存储null键和null值,HashMap可以存储null键和null值


2、LinkedHashMap
LinkedHashMap可以保证怎么存就怎么取,其原理和Set有点相似。Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。


3、TreeMap
也是相当于Set的改进,变为键值对形式存储。TreeMap类不仅实现了Map接口,还实现了java.util.SortMap接口,因此集合中的映射关系具有一定的顺序.但是在添加,删除,和定位映射关系上,TreeMap类比HashMap类的性能差一些.TreeMap类实现的Map集合中的映射关系是根据键值对象按一定的顺序排列的.因此不允许键对象是null.


各举一个例子解释一下吧
有一个Person类:

public class Person {public String name;public int age;public Person() {super();} public Person(String name,int age){this.name = name;this.age = age;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}public String getName() {return name;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Person other = (Person) obj;if (age != other.age)return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

1、HashMap

public static void main(String[] args) {HashMap<Person, String> hm = new HashMap<Person, String>();hm.put(new Person("Jack",23), "is a doctor");hm.put(new Person("Marry",24), "is a teacher");hm.put(new Person("Tom",22), "is a student");hm.put(new Person("Max",26), "is a worker");for (Entry<Person, String> en : hm.entrySet()) {System.out.println(en.getKey() + "  " +en.getValue());}}

得到的结果为:
Person [name=Max, age=26]  is a worker
Person [name=Jack, age=23]  is a doctor
Person [name=Marry, age=24]  is a teacher
Person [name=Tom, age=22]  is a student
存储是没有顺序的。


2、LinkedHashMap

public static void main(String[] args) {LinkedHashMap<Person, String> lhm = new LinkedHashMap<Person, String>();lhm.put(new Person("Jack",23), "is a doctor");lhm.put(new Person("Marry",24), "is a teacher");lhm.put(new Person("Tom",22), "is a student");lhm.put(new Person("Max",26), "is a worker");for (Entry<Person, String> en : lhm.entrySet()) {System.out.println(en.getKey() + "  " +en.getValue());}}

得到的结果为:
Person [name=Jack, age=23]  is a doctor
Person [name=Marry, age=24]  is a teacher
Person [name=Tom, age=22]  is a student
Person [name=Max, age=26]  is a worker
怎么存就怎么取。


3、TreeMap

public static void main(String[] args) {TreeMap<Person, String> tm = new TreeMap<Person, String>(new Comparator<Person>() {@Overridepublic int compare(Person p1, Person p2) {int num = p1.getName().compareTo(p2.getName());return num==0 ? p1.getAge()-p2.getAge() : num;}});tm.put(new Person("Jack",23), "is a doctor");tm.put(new Person("Marry",24), "is a teacher");tm.put(new Person("Tom",22), "is a student");tm.put(new Person("Max",26), "is a worker");for (Entry<Person, String> en : tm.entrySet()) {System.out.println(en.getKey() + "  " +en.getValue());}


得到的结果为:
Person [name=Jack, age=23]  is a doctor
Person [name=Marry, age=24]  is a teacher
Person [name=Max, age=26]  is a worker
Person [name=Tom, age=22]  is a student
这里是根据比较器,先比较名字,按字典排序,再比较年龄。若再添加一个tm.put(new Person("Jack",22), "is a doctor"),会输出结果:
Person [name=Jack, age=22]  is a doctor
Person [name=Jack, age=23]  is a doctor
Person [name=Marry, age=24]  is a teacher
Person [name=Max, age=26]  is a worker
Person [name=Tom, age=22]  is a student


好了,到这里集合框架的复习基本回顾完了。

原创粉丝点击