龙空技术网

初识java—(四十四)Map

IT研究僧 526

前言:

当前姐妹们对“java比较map”大概比较关心,朋友们都想要了解一些“java比较map”的相关资讯。那么小编同时在网上收集了一些有关“java比较map””的相关资讯,希望我们能喜欢,同学们快快来了解一下吧!

8.6 Map

引入:

根据之前学习的集合我们知道,一个集合中可以存放学生信息,那现在有这么一个问题需要我们解决,根据一个学生的学号找到一个学生的信息并打印输出。拿我们前边学习的List与Set集合来说我们要如何完成?我们可以遍历学生对象,然后根据条件匹配,拿到学生信息。很显然这可以完成工作,但有点麻烦。

针对这种情况,Java给我们提供了Map集合。

Map用于保存具有映射关系的数据,是以一种键值对的形式进行存放的。因此Map集合里保存着两组值,一组用于保存Map里的key,另外一组用于保存Map里的value,key和value都可以是任何引用类型的数据。而Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。

Key和value是一一对应的关系,即通过指定的key,总能找到唯一的value对象。Map里的key放在一起可以看成一个Set集合,实际上Map中包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。

Map中的所有value放在一起可以看成一个list集合,元素与元素之间可以重复,每个元素可以根据索引来查找。只是Map中的索引不再使用整数值,而是以另外一个对象作为索引。如果需要从Map中取出元素,则需要提供该元素的key索引。

Map接口中定义了如下常用方法:

Ø void clear():删除Map对象中所有的key-value对。

Ø Boolean containsKey(Object key):查询Map中是否包含指定的key,如果有则返回true。

Ø Boolean containsValue(Object value):查询Map中是否包含一个或多个Value,如果有返回true。

Ø Set entrySet():返回Map中包含的key-value对所组成的set集合,每个集合元素都是Map.Entry(Entry是Map的内部类)对象。

Ø Object get(Object key):返回指定key所对应的value,如果此Map中不包含该key,返回null。

Ø boolean isEmpty():查询Map是否为空,如果为空返回true。

Ø Set keySet():返回该Map中所有的key组成的Set集合。

Ø Object put(Object key,Object value):添加一个key-value对,如果当前Map中已有一个与该key相当的key-value对,则新的key-value对会覆盖原来的key-value对。这里这个值的返回,如果当前key值上没有东西,返回null。如果有东西再在当前key值上放东西,返回之前放在这个key地方的值。

Ø void putAll(Map m):将Map的实例对象m中的key-value对复制到本Map中。

Ø Object remove(Object key):删除指定key-value对,返回被删除key所关联的value,如果该key不存在,返回null。

Ø int size():返回该Map里key-value对的个数。

Ø Collection values():返回该Map中所有value组成的Collection。

Map中包含一个内部类Entry,该类封装了一个key-value对。Entry包含了如下三个方法:

Ø Object getKey():返回Entry里包含的key值。

Ø Object getValue():返回Entry里包含的value值。

Ø Object setValue(V value):设置该Entry里包含的value值,并返回新的value值。

举例1:

public static void main(String[] args) throws Exception{

Map<String,String> map = new HashMap<String,String>();

//首先往map中存放数据

map.put("one","zhangsan");

map.put("two", "lisi");

map.put("three","wangwu");

//取得map中key-value的数量

System.out.println(map.size());//3

//判断map中是否存在value为lisi的对象

System.out.println(map.containsValue("lisi"));//true

//判断map中是否存在key为one的对象

System.out.println(map.containsKey("one"));//true

//判断当前map对象是否是空对象,即不含任何元素对象

System.out.println(map.isEmpty());//false

//创建一个新的Map对象m2将m2中的key-value复制到map中去

Map<String,String> m2 = new HashMap<String,String>();

m2.put("four","zhaoliu");

m2.put("five", "qianqi");

map.putAll(m2);

//重新获取map的key-value的个数

System.out.println(map.size());//5

//删除指定key的key-value对

String one = map.remove("one");

System.out.println(one);//zhangsan

System.out.println(map.size());//4

//遍历map

//方式1,获取所有的键,根据键来拿值

Set<String> set = map.keySet();

for(String key:set){

String value = map.get(key);

System.out.println(key+”---”+value);

}

//方式2,获取键值对对象,遍历

Set<Map.Entry<String,String>> set = map.entrySet();

for(Map.Entry<String, String> entry : set){

System.out.println(entry.getKey()+"===="+entry.getValue());

}

//常用的方式3,根据key值进行遍历

Iterator<String> it = map.keySet().iterator();

while (it.hasNext()) {

String str = it.next();

System.out.println(str + "-" + map.get(str));

}

}

8.6.1 HashMap和Hashtable实现类

HashMap和Hashtable都是Map的典型实现类,两者之间的关系完全类似于ArrayList和Vector。除此之外两者之间的典型区别:

1、 Hashtable是一个线程安全的Map实现,但HashMap是线程不安全。所以HashMap比Hashtable性能更高一点。

2、 Hashtable不允许使用null作为key和value,而HashMap则可以。

举例1:

public static void main(String[] args) throws Exception{

Map map = newHashMap();

map.put(null, null);

System.out.println(map.size());

Map m2 = newHashtable();

m2.put(null, null);

System.out.println(m2.size());

}

HashMap正常执行,而Hashtable则报空指针异常错误。

注意:尽量不要使用可变对象作为HashMap的key,如果使用了可变对象作为了map的key,则在程序中尽量不要去修改变量。

举例2:

public static void main(String[] args) throws Exception{

String str = "abc";

Map map = new HashMap();

map.put(str, "zhangsan");

str = "123";

System.out.println(map.get(str)); //输出null

System.out.println(map.get("abc")); //输出zhangsan

}

这里添加一个key—value的存值问题。

(1) key:String—value:String

(2) key:Integer—value:String

(3) key:String—value:Student

(4) key:Student—value:String

第四种,当出现了两个参数一样的对象进行添加时,这个时候我只想添加一个进去,如何解决?

在相应的对象中重写相应的方法。

举例3:关于map集合的嵌套问题,比如说:

浪曦有高薪就业班,全日制班。而每个班里都有学生。那我想用集合存放浪曦所有的学生,我应该怎么定义集合。

public static void main(String[] args){

HashMap<String, HashMap<String, Student>> langsin = new HashMap<String, HashMap<String, Student>>();

HashMap<String, Student> E24 = new HashMap<String, Student>();

Student Est = new Student("张三", 24);

Student Est1 = new Student("张三1", 24);

E24.put("002", Est);

E24.put("012", Est1);

langsin.put("E24", E24);

HashMap<String, Student> F06 = new HashMap<String, Student>();

Student Fst = new Student("李四", 23);

Student Fst1 = new Student("李四1", 23);

F06.put("003", Fst);

F06.put("007", Fst1);

langsin.put("F06", F06);

Set<String> langsinSet = langsin.keySet();

for (String str : langsinSet) {

System.out.println(str);

HashMap<String, Student> Value = langsin.get(str);

Set<String> Set = Value.keySet();

for (String str1 : Set) {

Student stu = Value.get(str1);

System.out.println("\t" + str1 + "----" + stu);

}

}}

举例4:在HashMap中嵌套ArrayList集合。

public static void main(String[] args){

HashMap<String,ArrayList<Student>> hm = new HashMap<String,ArrayList<Student>>();

ArrayList<Student> al1 = new ArrayList<Student>();

Student l1st = new Student();

al1.add(l1st);

hm.put(“001”,al1);

ArrayList<String> al2 = new ArrayLIst<String>();

Sudnet l2st = new Student();

al2.add(l2st);

hm.put(“004”,al2);

Set<String> set = hm.keySet();

for(String str:set){

System.out.println(str);

ArrayList<Student> al = hm.get(str);

for(Student st:al){

System.out.println(st);

}

}

}

举例5:

ArrayList集合嵌套HashMap集合。

ArrayList<HashMap<String,String>> arr = new ArrayList<HashMap<String,String>>();

//数据添加

for (HashMap<String, String> hm : arr) {

Set<String> set = hm.keySet();

for (String key : set) {

String value = hm.get(key);

System.out.println(key + "---" + value);

}

}

举例6:

Map里一个Map里有一个Map。

Set<String> MapSet = czbkMap.keySet();

for (String MapKey : MapSet) {

System.out.println(MapKey);

HashMap<String, ArrayList<Student>> MapValue = langsinMap

.get(MapKey);

Set<String> MapValueSet = MapValue.keySet();

for (String MapValueKey : MapValueSet) {

System.out.println("\t" + MapValueKey);

ArrayList<Student> MapValueValue St= MapValue

.get(MapValueKey);

for (Student s : MapValueValue) {

System.out.println("\t\t" + s.getName() + "---"

+ s.getAge());

}

}

}

8.6.2 LinkedHashMap实现类

LinkedHashMap是HashMap的子类,同LinkedHashSet一样,LinkedHashMap在存储数据元素时同样使用了链表来维护key-value对的存放顺序,该链表负责维护Map的迭代顺序,迭代顺序与key-value对的插入顺序保持一致。

举例1:

publicstaticvoid main(String[] args) throws Exception{

Map<String,String> map = new HashMap<String,String>();

map.put("1", "zhangsan1");

map.put("2", "zhangsan2");

map.put("3", "zhangsan3");

map.put("10", "zhangsan1");

map.put("20", "zhangsan20");

map.put("30", "zhangsan30");

for(Map.Entry<String,String> entry : map.entrySet()){

System.out.println(entry.getKey()+"====="+entry.getValue());

}

}

输出结果:

3=====zhangsan3

20=====zhangsan20

2=====zhangsan2

10=====zhangsan1

1=====zhangsan1

30=====zhangsan30

举例2:

替换上例程序的中第一行代码

LinkedHashMap<String,String> map = new LinkedHashMap<String,String>();

输出结果:

1=====zhangsan1

2=====zhangsan2

3=====zhangsan3

10=====zhangsan1

20=====zhangsan20

30=====zhangsan30

8.6.3 Properties属性类

Properties类是Hashtable类的子类,该对象在处理属性文件时非常方便。Properties类可以把Map对象和属性文件关联起来,从而可以把Map对象中的key-value对写入到属性文件中,也可以把属性文件中的“属性名=属性值”加载到Map对象中。由于属性文件里的属性名、属性值只能是字符串类型,所有Properties里的key、value都是字符串类型。

该类的常用方法如下:

Ø String getProperty(String key):获取Properties中指定属性名对应的属性值。

Ø String getProperty(String key,String defaultValue):方法重载,获取Properties中指定属性名对应的属性值,如果此属性名不存在时,返回默认的defaultValue值。

Ø Object setProperty(String key,String value):设置属性值,类似于Map的put()方法。

Ø void load(InputStream inStream):从属性文件中加载key-value对。

Ø void store(OutputStream out,String comments):将Properties中的key-value对输入到指定的属性文件中。

属性文件格式:在windows系统下属性文件常以.ini进行结尾,在Java中属性文件以.properties结尾。

举例1:

public static void main(String[] args) throws Exception{

Properties prop = new Properties();

prop.setProperty("name","zhangsan");

prop.put("age","24");

prop.store(new FileOutputStream("./test.ini"), "注释内容");

Properties prop2 = new Properties();

//FileInputStream文件输入流,使用prop的load()方法进行加载文件

prop2.load(new FileInputStream("./test.ini"));

prop2.setProperty("gender", "male");

System.out.println(prop2.get("age"));

System.out.println(prop2.getProperty("name"));

//FileOutputStream文件输出流,使用prop的store()方法将porp对象的信息保存到指定的文件中

prop2.store(new FileOutputStream("./test.properties"), "属性文件");

}

程序输出结果:

bankCode = 62202 1602 0131 34567

bankPass = 123456

userName = zhangsan

userAge = 24

8.6.4 SortedMap接口与TreeMap实现类

如同Set接口派生出SortedSet子接口,SortedSet接口有一个实现类TreeSet一样,Map接口也有一个SortedMap接口,SortedMap接口也有一个实现类TreeMap。TreeMap就是一个红黑树数据结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对时,需要根据key对节点进行排序。TreeMap保证所有的key-value对都处于有序的状态。

TreeMap的两种排序方式:

1、 自然排序:TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则抛出ClassCastException(类型转换异常)。

2、 定制排序:创建TreeMap对象时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时不需要key实现Comparable接口。

TreeMap提供的常用方法如下:

Ø Map.Entry firstEntry():返回该Map中最小key所对应的key-value对,如果Map为空,则返回null。

Ø Object firstKey():返回该Map中最小key值,如果该Map为空,则返回null。

Ø Map.Entry lastEntry():返回Map中最大key所对应的key-value对,如果Map为空,则返回null。

Ø Object lastKey():返回该Map中最大key值,如果该Map为空,则返回null。

Ø Map.Entry higherEntry(Object key):返回该Map中位于key后一位的key-value对。如果后面不存在则返回为null。

Ø Object higherKey(Object key):返回该Map中位于key后一位的key值,如果后面不存在则返回为null。

Ø Map.Entry lowerEntry(Object key):返回该Map中位于key前一位的key-value对。如果前面不存在则返回为null。

Ø Object lowerKey(Object key):返回该Map中位于key前一位的key值。如果前面不存在则返回为null。

Ø SortedMap subMap(Object fromKey,Object toKey):返回该Map的子Map,其key的范围是从fromKey(包括)到toKey(不包括)。

Ø SortedMap tailMap(Object fromKey):返回该Map的子Map,其key的范围是大于fromkey(包括)的所有key。

Ø SortedMap headMap(Object toKey):返回该Map的子Map,其key的范围是小于toKey(不包括)的所有key。

举例1:

package com.langsin.test;

import java.util.Comparator;

import java.util.TreeMap;

class MyTest implements Comparable<Object>{

int count;

public MyTest(int count){

this.count = count;

}

public int compareTo(Object obj) {

MyTest te = (MyTest)obj;

return count>te.count?1:(count<te.count?-1:0);

}

}

publicclass TestTreeMap {

public static void main(String[] args) {

Comparator<MyTest> comp = new Comparator<MyTest>(){

public int compare(MyTest m1, MyTest m2) {

if(m1.count>m2.count){

return -1;

}

if(m1.count<m2.count){

return 1;

}

return 0;

}

};

//首先实现treeMap的定制排序

TreeMap<MyTest,String> map = new TreeMap<MyTest,String>();

map.put(new MyTest(-3), "123");

map.put(new MyTest(1), "456");

map.put(new MyTest(3), "789");

System.out.println(map);

System.out.println(map.firstEntry());

}

}

8.6.5 WeakHashMap实现类

WeakHashMap与HashMap的用法基本相似,区别在于HashMap的key保留了对实际对象的强引用。即:只要HashMap不被销毁,该HashMap的所有key所引用的对象就不会被垃圾回收,HashMap也不会自动删除这些key所对应key-value对。WeakHashMap的key只保留了对实际对象的弱引用,即:WeakHashMap的对象的key所引用的对象没有被其他强引用变量所引用,则这些key所引用的对象可能被垃圾回收,WeakHashMap也可能自动删除这些key所对应的key-value对。

对于WeakHashMap,大家仅作了解,知道与HashMap的区别即可。

举例1:

publicstaticvoid main(String[] args) throws Exception{

WeakHashMap map = newWeakHashMap();

map.put(new String("123"), "123");

String str = newString("456");

map.put(str, "456");

map.put("456", "abc");

System.out.println(map); //输出内容

System.gc();

System.out.println(map);

}

8.6.7 EnumMap实现类

EnumMap是一个与枚举类一起使用的Map实现,EnumMap中所有的key都必须是单个枚举类的枚举值。创建EnumMap时必须显示或隐式指定它对应的枚举类。

EnumMap根据key的自然顺序,即在枚举类中的定义顺序来维护key-value对的顺序。调用Map的方法keySet()、entrySet()、values()遍历EnumMap时可以看到这种顺序。

EnumMap不允许使用null作为key,但允许使用null作为value。

创建EnumMap时必须指定一个枚举类,从而与使EnumMap和指定枚举类关联起来。

举例1:

publicstaticvoid main(String[] args) throws Exception{

Map map = new EnumMap(Planet.class);

map.put(Planet.EARTH, "地球");

map.put(Planet.MARS, "火星");

//map.put(Planet.PLUTO, "冥王星");

map.put(Planet.VENUS, "金星");

map.put(Planet.SATURN, "土星");

map.put(Planet.JUPITER, "木星");

map.put(Planet.MERCURY, "水星");

map.put(Planet.NEPTUNE, "海王星");

map.put(Planet.URANUS, "天王星");

System.out.println(map);

}

标签: #java比较map