Map集合
1. 概述
Map<K, V>集合是一个接口,和Collection集合不同的是,它是双列集合,也就是说它所存储的是键值对。2. 特点
- Map集合存储的是键值对,其中键要求唯一。
- Map集合的键对应一个值,值不要求唯一,但是一个键不能对应对个值。
- Map集合没有Iterator迭代器,如果需要迭代需要转化为单列集合间接迭代。
3. 继承关系
Map|--Hashtable:哈希表结构,不保证存取顺序,不允许null键或者null值,线程安全,效率较低,已被HashMap替代
|--Propertise:键值对均是String类型的Map集合,包括直接对流操作的方法,专为配置文件而生。
|--HashMap:哈希表结构,不保证存取顺序,允许null键和null值,非线程安全,效率较高。
|--LinkedHashMap:带双向链表的哈希表结构,保持存取顺序,允许null键和null值,非线程安全,效率较高。
|--TreeMap:平衡排序二叉树(红黑树)结构,按自然排序或比较器存入元素以保证元素有序,非线程安全。
元素唯一性取决于ComparaTo方法或Comparator比较器。
4. 常用方法
Map集合的方法一部分和Set集合类似。- 添加键值对
V put(K key, V value) - 根据键获取值
V get(Object key) - 判断是否包含键或者值
boolean containsKey(Object key)
boolean containsValue(Object value) - 删除对应键值对
V remove(Object key)
default boolean remove(Object key, Object value) - 替换新值
default V replace(K key, V value) // 返回老值
default boolean replace(K key, V oldValue, V newValue) - 获取entrySet(包含所有键值对的Map对象的Set集合)
Set<Map.Entry<K,V>> entrySet() - 获取包含所有键的Set集合
Set<K> keySet() - 获取包含所有值的Collection集合
Collection<V> values()
示例
package collection.map;
import java.util.HashMap;
import java.util.Map;
public class MapFunc {
public static void main(String[] args) {
/*
* Map集合的使用
* 1. Map集合中的键是唯一的。
* 2. Map集合没有迭代器,如果需要迭代需要转成单列集合。
*/
Map<String, String> map = new HashMap<String, String>();
// 添加元素
map.put("星期一", "Monday"); // 返回值为null
map.put("星期二", "Tuesday");
map.put("星期三", null); // HashMap可以存储null值
map.put("星期二", "Tues"); // 如果键相同,则值覆盖,并返回原有旧值。
// 给定键获取值
String value = map.get( "星期二"); // " Tues"
// 判断是否包含键和值
boolean b1 = map.containsKey( "星期三"); // true
boolean b2 = map.containsValue( "Tuesday"); // false
// 给定键删除。
String str1 = map.remove( "星期三"); // null
// 替换(修改)
String str2 = map.replace( "星期一", "Mon" ); // "Monday"
}
}
注意
Map.Entry是Map接口中的内部接口,因为依托Map集合存在而存在,并且由于该接口能够获取Map集合中的所有键值对,所以定义在内部。5. 迭代
方法一:使用entrySet集合方法二:使用keySet集合示例
package collection.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Map_Demo {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
// 添加元素
map.put("Mon", "星期一");
map.put("Tues", "星期二");
map.put("Wed", "星期三");
map.put("Thur", "星期四");
map.put("Fir", "星期五");
map.put("Sat", "星期六");
map.put("Sun", "星期日");
// 通过keySet方法获取所有键值
Set<String> keySet = map.keySet();
for (String key : keySet) {
String value = map.get( key);
}
// 通过entrySet方法获取所有键值
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
String entryKey = entry.getKey();
String entryValue = entry.getValue();
}
// 获取所有值
Collection<String> allvalues = map .values();
}
}
HashMap集合与TreeMap集合
特点
- 其方法和思想均和HashSet以及TreeSet高度类似,可以参照。
- HashMap的键保持唯一性,取决于hashCode以及equals方法。
TreeMap的键保持唯一性,取决于比较方法和比较器。
键唯一性示例
ComparatorOnlyByAge.javapackage comparator;
import java.util.Comparator;
import bean.Person;
public class ComparatorOnlyByAge implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1 .getAge() - o2 .getAge();
}
}
MapSubclass.java
package collection.map;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import bean.Person;
import comparator.ComparatorOnlyByAge;
public class MapSubclass {
public static void main(String[] args) {
// 注意:HashMap判断键是否相同的依据是hashCode和equals方法。
Map<Person, String> mapHash = new HashMap<Person, String>();
mapHash.put(new Person( "jacob", 25), "huainan" );
mapHash.put(new Person( "hanlin", 26), "beijing" );
mapHash.put(new Person( "meteor", 25), "shanghai" );
for (Person key : mapHash.keySet()) {
System.out.println( "(" + key + "," + mapHash.get(key ) + ")" );
}
System.out.println( "-------------------");
// 注意:TreeMap判断键是否相同的依据是比较方法或比较器。
Map<Person, String> mapTree = new TreeMap<Person, String>(new ComparatorOnlyByAge());
mapTree.put(new Person( "jacob", 25), "huainan" );
mapTree.put(new Person( "hanlin", 26), "beijing" );
mapTree.put(new Person( "meteor", 25), "shanghai" );
mapTree.put(new Person( "yuhang", 25), "xi'an" );
mapTree.put(new Person( "huangdeng", 26), "guangzhou");
for (Person key : mapTree.keySet()) {
System.out.println( "(" + key + "," + mapTree.get(key ) + ")" );
}
}
}
运行结果
(Person [name=hanlin, age=26],beijing)(Person [name=meteor, age=25],shanghai)(Person [name=jacob, age=25],huainan)-------------------(Person [name=jacob, age=25],xi'an)(Person [name=hanlin, age=26],guangzhou)案例
获取字符串中每个字母出现的次数package collection;
import java.util.Map;
import java.util.TreeMap;
public class Map_Test {
public static void main(String[] args) {
/*
* 获取字符串中每一个字母出现的次数。
* 要求返回结果个格式是 a(1)b(2)d(4)......,并且不应包含符号;
* 思路:
* 1. 获取到字符串中的每一个字母。
* 2. 用字母取查表,如果查到了该字母对应的次数,就将这个次数+1后重新存回表中。
* 如果没有查到呢?将该字母和1存到表中。
* 3. 每一字母都查完表后,表中记录的就是所有字母出现的次数。
*
* 字母和次数之间存在对应关系,而且字母是唯一性的,所以可以使用map集合做表进行查询。
* 通过结果发现 字母有顺序的,所以可以通过map集合中的 treemap作为表。
*/
String str = "an+object+that+maps+keys+to+values.+a+map+cannot+contain+duplicate+keys;"
+ "+each+key+can+map+to+at+most+one+value.this+interface+takes+the+place+of=the="
+ "dictionary=class,=which=was=a=totally=abstract=class=rather than=an=interface."
+ "the map interface provides three collection views, which/allow/a/map's/contents"
+ "/to/be/viewed/as/a/set/of/keys,/collection/of/values,/or/set/of/key-value/mappings." ;
Map<Character, Integer> map = getCharCount(str);
String result = printCharCount(map );
System.out.println( result);
}
public static String printCharCount(Map<Character, Integer> map) {
StringBuilder str = new StringBuilder();
for (Character key : map.keySet()) {
str.append(key ).append("(" ).append(map .get(key )).append(")" );
}
return str.toString();
}
public static Map<Character, Integer> getCharCount(String str) {
// 将字符串转成数组,方便对每一个字符做判断处理
char[] chs = str.toCharArray();
Map<Character, Integer> map = new TreeMap<Character, Integer>();
for (int i = 0; i < chs.length; i++) {
// 如果不是字母,则继续下一次循环
if (!Character. isAlphabetic(chs[i])) continue;
Character key = chs[ i];
int value = 0;
// 如果该字母已被记录,则获取该字母已出现的次数;否则次数就初始化为0
if (map.containsKey( key)) {
value = map.get( key);
}
// 将该次数自增并记录
map.put(key, ++value);
}
return map;
}
}
运行结果
a(39)b(3)c(21)d(4)e(37)f(7)g(1)h(13)i(16)j(1)k(6)l(16)m(7)n(18)o(22)p(10)r(10)s(23)t(33)u(5)v(7)w(6)y(7)Properties集合
特点
- Properties集合表示了一个持久的属性集。
- Properties集合键值对均是String类型。
- Properties集合可以直接从一个流中读取数据,也可以直接保存到一个流中。
- 强烈建议Properties集合只存储String类型的数据,尽管可以利用其父类方法存储其他类型数据。
常用方法
- 添加属性值
Object setProperty(String key, String value) - 获取属性值
String getProperty(String key)
String getProperty(String key, String defaultValue) - 获取所有属性
Set<String> stringPropertyNames() - 打印所有属性和属性值
void list(PrintStream out)
void list(PrintWriter out) - 将属性集存储到流中(可以使用XML方式)
void store(OutputStream out, String comments)
void store(Writer writer, String comments)
void storeToXML(OutputStream os, String comment)
void storeToXML(OutputStream os, String comment, String encoding) - 从流中读取属性集(可以使用XML方式)
void load(InputStream inStream)
void load(Reader reader)
void loadFromXML(InputStream in)
示例
package collection.map;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class PropertiseDemo {
public static void main(String[] args) {
Properties pro = new Properties();
// 1. 添加属性
pro.setProperty( "name" , "Windows 7" );
pro.setProperty( "date" , "2014.12.15" );
pro.setProperty( "time" , "17:20" );
pro.setProperty( "bit" , "x64" );
pro.setProperty( "lan" , "zh" );
// 2. 获取属性
String str1 = pro.getProperty( "name" ); // "Windows 7"
String str2 = pro.getProperty( "OS" , "none" ); // "none"
// 3. 获取所有属性
Set<String> set = pro.stringPropertyNames(); // [name, date, lan, time, bit]
// 4. 存储属性集到流中
File file = new File( "temp\\Properties.xml" );
try {
pro.storeToXML( new FileOutputStream( file), "PropertiesDemo" );
} catch (IOException e) {
e.printStackTrace();
}
// 5. 从流中读取属性集
Properties proFromXml = new Properties();
try {
proFromXml.loadFromXML( new FileInputStream( file));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println( proFromXml);
}
}