【JAVA集合框架之Map】
一、概述。
1.Map是一种接口,在JAVA集合框架中是以一种非常重要的集合。
2.Map一次添加一对元素,所以又称为“双列集合”(Collection一次添加一个元素,所以又称为“单列集合”)
3.Map集合中存放的是一个一个的键值对,集合中存放的元素必须保证键的唯一性。
二、常用方法。
1.添加
V |
put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。 |
该方法的作用就是向集合中添加一个键值对,并返回一个值;如果键存在,则返回对应的旧值,并以新值取代之;如果键不存在则返回null。所以该方法也是修改的方法。
void |
putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。 |
该方法功能略,但注意泛型上限的使用。比较Collection方法:
boolean |
addAll(Collection<? extends E> c) 将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。 |
2.删除
V |
remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。 |
该方法根据键删除一个键值对,并返回值。如果没有这个键值对,将返回null。
void |
clear() 从此映射中移除所有映射关系(可选操作)。 |
该方法功能就是清空集合。
3.判断
boolean |
containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。 |
boolean |
containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。 |
这两个方法,前者判断是否存在指定键,后者判断是否存在指定值。
boolean |
isEmpty() 如果此映射未包含键-值映射关系,则返回 true。 |
该方法用于判断该Map集合是否为空集合。
4.获取。
V |
get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null 。 |
int |
size() 返回此映射中的键-值映射关系数。 |
这两个方法,前者根据指定的键获取对应的值,如果集合中没有指定的键,则返回null;后者获取键值对的个数。
以上的方法为基本方法,重点方法在下面。
三、重点:Map集合的四种遍历方式。
1.第一种遍历方式:使用keySet方法。
Set<K> |
keySet() 返回此映射中包含的键的 Set 视图。 |
该方法会返回一个包含所有键的Set集合。
遍历过程:先得到所有键的集合,遍历集合,根据键得到所有的值。
package p01.traverseDemo01.keySetDemo; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; public class KeySetDemo { public static void main(String[] args) {
Demo01();
} private static void Demo01() {
Map<Integer,String>map=new HashMap<Integer,String>();
map.put(1, "wangcai");
map.put(2, "xiaoqiang");
map.put(3, "xiaoming"); Set<Integer>set=map.keySet();
for(Iterator<Integer>it=set.iterator();it.hasNext();)
{
Integer key=it.next();
String value=map.get(key);
System.out.println(key+":"+value);
} } }
应当注意,结果是无序的,这是因为采用了HashMap作为示例,HashMap底层的数据结构是哈希表,存储元素的时候有自己的规则,所以无序。
2.第二种遍历方式:使用entrySet方法。
Set<Map.Entry<K,V>> |
entrySet() 返回此映射中包含的映射关系的 Set 视图。 |
此方法返回值也是一个Set集合,但是存储的内容是Map.Entry对象。Map.Entry是什么东西?
JDK1.6API的解释如下:
嵌套类摘要 | |
---|---|
static interface |
Map.Entry<K,V> 映射项(键-值对)。 |
虽然API的解释是“嵌套类”,但是Map是一个接口,Entry也是一个接口,事实上Map.Entry是Map的一个内部静态接口。
该接口封装了几个方法,用于操作一个键值对,注意,是一个,因为它仅仅对一个键值对进行封装(确切的说是对操作每个键值对的方法进行了封装,每个键值对对应着一个Map.Entry对象)。
Map.Entry接口的方法如下:
方法摘要 | |
---|---|
boolean |
equals(Object o) 比较指定对象与此项的相等性。 |
K |
getKey() 返回与此项对应的键。 |
V |
getValue() 返回与此项对应的值。 |
int |
hashCode() 返回此映射项的哈希码值。 |
V |
setValue(V value) 用指定的值替换与此项对应的值(可选操作)。 |
以上方法中,最常用的是getKey方法和getValue方法。
遍历过程:首先拿到每一个键值对对象Map.Entry的集合,再通过遍历集合拿到所有的键值对。
package p01.traverseDemo01.keySetDemo; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; public class KeySetDemo { public static void main(String[] args) {
Demo01();
} private static void Demo01() {
Map<Integer,String>map=new HashMap<Integer,String>();
map.put(1, "wangcai");
map.put(3, "xiaoming");
map.put(2, "xiaoqiang"); Set<Integer>set=map.keySet();
for(Iterator<Integer>it=set.iterator();it.hasNext();)
{
Integer key=it.next();
String value=map.get(key);
System.out.println(key+":"+value);
} } }
3.第三种遍历方式:使用values方法。
Collection<V> |
values() 返回此映射中包含的值的 Collection 视图。 |
此种方法可以返回值的Collection集合,比较返回值,第一种方式使用keySet方法,返回值类型是Set集合,这里为什么不是Set集合?
解析:Map中键是唯一的,所以使用Set集合存储,而值可以重复,所以使用Collection集合存储。
package p01.traverseDemo03.valuesDemo; import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; public class ValuesDemo { public static void main(String[] args) {
Demo01();
} private static void Demo01() {
Map<Integer,String>map=new HashMap<Integer,String>();
map.put(1, "wangcai");
map.put(3, "xiaoming");
map.put(2, "xiaoqiang"); Collection<String>coll=map.values();
for(Iterator<String>it=coll.iterator();it.hasNext();)
{
String value=it.next();
System.out.println(value);
} } }
4.第四种遍历方式:使用增强型for循环间接遍历。
package p11.ArraysDemo.p01.ExtendForCircle; import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; /**
* 使用增强型for循环实现Map的三种遍历方式
* @author kuangdaoyizhimei
*
*/
public class ExtendForCircle { public static void main(String[] args) {
Map<Integer,String>map=new HashMap<Integer,String>();
map.put(1, "xiaoqiang");
map.put(2, "zhangsan");
map.put(3, "lisi");
map.put(4, "wangwu");
Function1(map);
Function2(map);
Function3(map);
} private static void Function3(Map<Integer, String> map) {
Set<Map.Entry<Integer, String>>set=map.entrySet();
for(Map.Entry<Integer, String>kv:set)
{
Integer key=kv.getKey();
String value=kv.getValue();
System.out.println("Key:"+key+"\tvalue:"+value);
}
} private static void Function2(Map<Integer, String> map) {
Collection<String>list=map.values();
for(String val:list)
{
System.out.println(val);
}
System.out.println();
System.out.println();
} private static void Function1(Map<Integer, String> map) {
Set<Integer>set=map.keySet();
for(Integer i:set)
{
System.out.println(i+":"+map.get(i));
}
System.out.println();
System.out.println();
} }
四、Map集合的常见子类。
public class Hashtable<K,V>extends Dictionary<K,V>implements Map<K,V>, Cloneable, Serializable |
public class HashMap<K,V>extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable |
public class TreeMap<K,V>extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, Serializable |
这三者有些区别:
HashTable:内部结构是哈希表,JDK1.0就出现了(JDK1.0出现的单列集合只有Vector,双列集合只有HashTable),是同步的。不允许null作为键值。
HashMap:内部结构是哈希表,是非同步的。允许null作为键值。
TreeMap:内部结构是一棵红黑树,可以对Map集合中的键进行排序。
需要注意的是Set集合的实现依赖于HashMap集合----HashMap将值统一为一个对象而只关注键的操作即可实现Set集合中元素的唯一性。
HashTable有一个子类应当特别注意:Properties
public class Propertiesextends Hashtable<Object,Object> |
这个类用来存储键值对型的文件配置信息,它和Io技术相结合才能发挥出它的优势。
1.HashMap类。
Hash代表着底层的实现使用了哈希表,所以如果使用自定义对象作为键,应当注意重写类的hashCode方法和equals方法。
示例:使用HashMap存储自定义对象Student和其归属地NativePlace,并遍历。
package p02.SubClassDemo01.HashMapDemo; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; class Student
{
private String name;
private int age;
@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;
Student other = (Student) 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 Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
} class NativePlace
{
private String province;
private String city;
public NativePlace(String province, String city) {
super();
this.province = province;
this.city = city;
}
public NativePlace() {
super();
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
public class HashMapDemo { public static void main(String[] args) {
Demo01();
} private static void Demo01() {
HashMap<Student,NativePlace>hm=new HashMap<Student,NativePlace>();
hm.put(new Student("wangwu",25), new NativePlace("hubei","suizhou"));
hm.put(new Student("zhaoliu",26), new NativePlace("hunan","chagnsha"));
hm.put(new Student("zhangsan",23), new NativePlace("shandong","zibo"));
hm.put(new Student("lisi",24), new NativePlace("shandong","weifang")); //重复添加无效
hm.put(new Student("wangwu",25), new NativePlace("hubei","suizhou"));
hm.put(new Student("zhaoliu",26), new NativePlace("hunan","chagnsha"));
hm.put(new Student("zhangsan",23), new NativePlace("shandong","zibo"));
hm.put(new Student("lisi",24), new NativePlace("shandong","weifang")); for(Iterator<Map.Entry<Student,NativePlace>>it=hm.entrySet().iterator();it.hasNext();)
{
Map.Entry<Student, NativePlace>me=it.next();
Student stu=me.getKey();
NativePlace np=me.getValue();
System.out.println(stu.getName()+":"+np.getProvince()+"."+np.getCity());
} } }
2.TreeMap类。
TreeMap类底层使用了排序树,如果使用自定义对象作为键,就必须实现Comparable接口;如果没有实现这个接口,则必须使用比较器作为HashTree初始化对象的参数。
现在将上面的代码中Student的hashCode方法以及equals方法删掉,同时实现接口Comparable,重写compareTo方法,以达到按照年龄排序的目的。
package p02.SubClassDemo02.TreeMapDemo; import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap; class Student implements Comparable<Student>
{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Student o) {
int temp=this.age-o.getAge();
return temp==0?this.name.compareTo(o.getName()):temp;
}
} class NativePlace
{
private String province;
private String city;
public NativePlace(String province, String city) {
super();
this.province = province;
this.city = city;
}
public NativePlace() {
super();
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
} public class TreeMapDemo { public static void main(String[] args) {
Demo01();
} private static void Demo01() {
TreeMap<Student,NativePlace>hm=new TreeMap<Student,NativePlace>();
hm.put(new Student("wangwu",25), new NativePlace("hubei","suizhou"));
hm.put(new Student("zhaoliu",26), new NativePlace("hunan","chagnsha"));
hm.put(new Student("zhangsan",23), new NativePlace("shandong","zibo"));
hm.put(new Student("lisi",24), new NativePlace("shandong","weifang")); //重复添加无效
hm.put(new Student("wangwu",25), new NativePlace("hubei","suizhou"));
hm.put(new Student("zhaoliu",26), new NativePlace("hunan","chagnsha"));
hm.put(new Student("zhangsan",23), new NativePlace("shandong","zibo"));
hm.put(new Student("lisi",24), new NativePlace("shandong","weifang")); for(Iterator<Map.Entry<Student,NativePlace>>it=hm.entrySet().iterator();it.hasNext();)
{
Map.Entry<Student, NativePlace>me=it.next();
Student stu=me.getKey();
NativePlace np=me.getValue();
System.out.println(stu.getName()+":"+stu.getAge()+"----"+np.getProvince()+"."+np.getCity());
} } }
运行可以看出重复添加的元素仍然没有添加进去,因为TreeSet判断元素是否相同的依据是compareTo方法的返回值而不是hashCode方法以及equals方法。
如果现在有了新的需求,需要按照新的规则对学生进行排序,则创建比较器,按照比较器中的新规则进行排序。
package p02.SubClassDemo02.TreeMapDemo; import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap; class Student implements Comparable<Student>
{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Student o) {
int temp=this.age-o.getAge();
return temp==0?this.name.compareTo(o.getName()):temp;
}
} class NativePlace
{
private String province;
private String city;
public NativePlace(String province, String city) {
super();
this.province = province;
this.city = city;
}
public NativePlace() {
super();
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
} class CompareByName implements Comparator<Student>
{
@Override
public int compare(Student o1, Student o2) {
int temp=o1.getName().compareTo(o2.getName());
return temp==0?o1.getAge()-o2.getAge():temp;
}
}
public class TreeMapDemo {
public static void main(String[] args) {
Demo01();
} private static void Demo01() {
TreeMap<Student,NativePlace>hm=new TreeMap<Student,NativePlace>(new CompareByName());
hm.put(new Student("wangwu",25), new NativePlace("hubei","suizhou"));
hm.put(new Student("zhaoliu",26), new NativePlace("hunan","chagnsha"));
hm.put(new Student("zhangsan",23), new NativePlace("shandong","zibo"));
hm.put(new Student("lisi",24), new NativePlace("shandong","weifang")); //重复添加无效
hm.put(new Student("wangwu",25), new NativePlace("hubei","suizhou"));
hm.put(new Student("zhaoliu",26), new NativePlace("hunan","chagnsha"));
hm.put(new Student("zhangsan",23), new NativePlace("shandong","zibo"));
hm.put(new Student("lisi",24), new NativePlace("shandong","weifang")); for(Iterator<Map.Entry<Student,NativePlace>>it=hm.entrySet().iterator();it.hasNext();)
{
Map.Entry<Student, NativePlace>me=it.next();
Student stu=me.getKey();
NativePlace np=me.getValue();
System.out.println(stu.getName()+":"+stu.getAge()+"----"+np.getProvince()+"."+np.getCity());
} } }
可以看到,通过使用比较器,确实达到了按照名字字典序排序的目的,这也证明了如果使用比较器,则原来的自然比较方式将会无效。
3.LinkedHashMap类。
此类的是HashMap的子类,与HashMap相比,该类实现了“有序”,即插入和取出的顺序一致。该类在很多时候都能发挥出很大的作用。
【JAVA集合框架之Map】的更多相关文章
- Java集合框架之map
Java集合框架之map. Map的主要实现类有HashMap,LinkedHashMap,TreeMap,等等.具体可参阅API文档. 其中HashMap是无序排序. LinkedHashMap是自 ...
- Java集合框架之Map接口浅析
Java集合框架之Map接口浅析 一.Map接口综述: 1.1java.util.Map<k, v>简介 位于java.util包下的Map接口,是Java集合框架的重要成员,它是和Col ...
- Java集合框架中Map接口的使用
在我们常用的Java集合框架接口中,除了前面说过的Collection接口以及他的根接口List接口和Set接口的使用,Map接口也是一个经常使用的接口,和Collection接口不同,Map接口并不 ...
- java集合框架07——Map架构与源代码分析
前几节我们对Collection以及Collection中的List部分进行了分析,Collection中还有个Set,因为Set是基于Map实现的,所以这里我们先分析Map,后面章节再继续学习Set ...
- Java 集合框架之 Map
Hashtable Hashtable 的实例有两个参数影响其性能:初始容量 和加载因子.容量 是哈希表中桶 的数量,初始容量就是哈希表创建时的容量.注意,哈希表的状态为 open:在发生“哈希冲突” ...
- 【转】Java集合框架List,Map,Set等全面介绍
原文网址:http://android.blog.51cto.com/268543/400557 Java Collections Framework是Java提供的对集合进行定义,操作,和管理的包含 ...
- 34、Java集合框架List,Map,Set等全面介绍(转载)
Java Collections Framework是Java提供的对集合进行定义,操作,和管理的包含一组接口,类的体系结构. Java集合框架的基本接口/类层次结构: java.util.C ...
- Java集合框架List,Map,Set等全面介绍
Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I] +--java.util.ArrayList [C] +- ...
- 我所理解Java集合框架的部分的使用(Collection和Map)
所谓集合,就是和数组类似——一组数据.java中提供了一些处理集合数据的类和接口,以供我们使用. 由于数组的长度固定,处理不定数量的数据比较麻烦,于是就有了集合. 以下是java集合框架(短虚线表示接 ...
随机推荐
- BZOJ 2438: [中山市选2011]杀人游戏
Description 给你一个有向图,求至少询问多少次能够得到全部点的信息. Sol Tarjan + 强连通分量缩点 + 判断. 先缩点,如果我们知道了强连通分量里的任意一个点,我们就可以知道这些 ...
- xadmin 自定义视图在uwsgi部署时的一坑
比如修改登录页的template,代码如下: xadmin.site.register(xadmin.views.LoginView, login_template="card_pool/s ...
- Junit 测试 Spring
在测试类上加上@RunWith,和@ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration ...
- XAMPP端口占用启动不了
skype默认会占用80和443端口 如果在apache之前启动skype,apache就会启动不了了!! 解决办法很简单: 1. 先启动apache再启动skype,这样skype就会换其他的端口监 ...
- EOS/普元:概述:中国IT业的悲哀
公司引入了普元的EOS作为公司的基础架构平台,今后的所有项目将逐步向EOS的迁移,但对EOS的研究又让我不得不说出以下话: 1.EOS确实够简单,但未免简单过了头:从语言层面看EOS 因为EOS将成为 ...
- SSRS报表参数设置
一.日期时间类型的参数注意事项: 关于数据类型的选择:(只有数据类型设置为日期/时间格式,在查询的时候才会显示日期控件,提示信息一般改成汉字) 指定默认值:指定开始日期为前10天,
- 77 找出最大连续自然数个数[Longest Consecutive Sequence in an Unsorted Array]
[本文链接] http://www.cnblogs.com/hellogiser/p/Longest-Consecutive-Sequence-in-an-Unsorted-Array.html [题 ...
- java访问数据库的sql
drop database if exists STOREDB;create database STOREDB;use STOREDB; create table CUSTOMERS ( ID big ...
- ACM/ICPC 之 Floyd+记录路径后继(Hdu1385(ZOJ1456))
需要处理好字典序最小的路径 HDU1385(ZOJ1456)-Minimum Transport //Hdu1385-ZOJ1456 //给定邻接矩阵,求给定起点到终点的最短路径,若有相同路长的路径按 ...
- iOS-UIView 之 layoutMargins & preservesSuperviewLayoutMargins 解惑
这里先看下苹果给出的解释: iOS8.0之后,uiview默认layoutMargins 为(8,8,8,8),也可以自己指定,仅适用于自动布局:当添加子view到父view上时,这样设置好约束 默认 ...