之前复习完了List和Set的内容,剩下Map的内容也一起复习了。
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public 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>() {
@Override
public 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
好了,到这里集合框架的复习基本回顾完了。