Home

韧桂

思考,总结

Map接口

一、Map接口

  • Map 与 Collection 并列存在。用于保存具有映射关系的数据:Key-Value
  • Map 中的 key 和 value 都可以是任何引用类型的数据
  • Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写 hashCode() 和 equals() 方法。
  • 常用 String 类作为 Map 的“键”。
  • key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value。

二、Map 的常用实现类 HashMap 及主要方法的使用

  • Map接口的常用实现类:HashMap、TreeMap和Properties。
  • HashMap是 Map 接口使用频率最高的实现类。
  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
  • HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
  • HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

三、以HashMap为例谈 Map 的遍历

四、Map 实现类之二:LinkedHashMap 的使用

  • LinkedHashMap 是 HashMap 的子类
  • 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

五、Map 实现类之三:TreeMap 的使用

  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
  • TreeMap 的 Key 的排序:
    • 自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
    • 定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
  • TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
  • 若使用自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。

六、Map 实现类之四:Hashtable 的子类 Properties 的使用 (一)

  • Hashtable是个古老的 Map 实现类,线程安全。
  • 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
  • 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
  • Hashtable判断两个key相等、两个value相等的标准,与hashMap一致。

(二)

代码一:

package thirteen;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

import org.junit.Test;

/*
 * Collection接口
 * 
 * Map接口
 * 		|-----HashMap:Map的主要实现类
 * 		|-----LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按添加的顺序遍历的。
 * 		|-----TreeMap:按照添加进Map中的元素的key的指定属性进行排序。要求:key必须是同一个类的对象!
 * 				针对key:自然排序   vs 定制排序
 * 		|-----Hashtable:古老的实现类,线程安全,不建议使用。
 * 			|----Properties:常用来处理属性文件。键和值都为String类型的
 */
public class TestMap {
	//使用Properties处理属性文件
	@Test
	public void test6() throws FileNotFoundException, IOException{
		Properties pros = new Properties();
		pros.load(new FileInputStream(new File("jdbc.properties")));
		String user = pros.getProperty("user");
		System.out.println(user);
		String password = pros.getProperty("password");
		System.out.println(password);
	}

	//TreeMap 的使用
	// 定制排序
	@Test
	public void test5() {
		Comparator com = new Comparator() {
			public int compare(Object o1, Object o2) {
				if (o1 instanceof Customer && o2 instanceof Customer) {
					Customer c1 = (Customer) o1;
					Customer c2 = (Customer) o2;
					int i = c1.getId().compareTo(c2.getId());
					if (i == 0) {
						return c1.getName().compareTo(c2.getName());
					}
					return i;
				}
				return 0;
			}
		};
		TreeMap map = new TreeMap(com);
		map.put(new Customer("AA", 1001), 87);
		map.put(new Customer("CC", 1001), 67);
		map.put(new Customer("MM", 1004), 77);
		map.put(new Customer("GG", 1002), 97);
		
		Set set1 = map.keySet();
		for (Object obj : set1) {
			System.out.println(obj + "----->" + map.get(obj));
		}
	}

	// 自然排序
	@Test
	public void test4() {
		Map map = new TreeMap();
		map.put(new Person("AA", 23), 89);
		map.put(new Person("MM", 22), 79);
		map.put(new Person("GG", 23), 99);
		map.put(new Person("JJ", 13), 69);

		Set set1 = map.keySet();
		for (Object obj : set1) {
			System.out.println(obj + "----->" + map.get(obj));
		}
	}

	//LinkedHashMap 的使用
	@Test
	public void test3() {
		Map map = new LinkedHashMap();
		map.put("AA", 213);
		map.put("BB", 45);
		map.put(123, "CC");
		map.put(null, null);
		map.put(new Person("DD", 23), 89);

		Set set1 = map.keySet();
		for (Object obj : set1) {
			System.out.println(obj + "----->" + map.get(obj));
		}
	}

	/*
	 * 以HashMap为例谈 Map 的遍历:
	 *  //元视图操作的方法:
	 * Set keySet()
	 * Collection values()
	 * Set entrySet()
	 */
	@Test
	public void test2() {
		Map map = new HashMap();
		map.put("AA", 213);
		map.put("BB", 45);
		map.put(123, "CC");
		map.put(null, null);
		map.put(new Person("DD", 23), 89);

		// 1.遍历key集。
		Set set = map.keySet();
		for (Object obj : set) {
			System.out.println(obj);
		}
		// 2.遍历value集
		System.out.println();
		Collection values = map.values();
		Iterator i = values.iterator();
		while (i.hasNext()) {
			System.out.println(i.next());
		}
		// 3.如何遍历key-value对。
		System.out.println();
		// 方式一:
		Set set1 = map.keySet();
		for (Object obj : set1) {
			System.out.println(obj + "----->" + map.get(obj));
		}
		// 方式二:
		System.out.println();
		Set set2 = map.entrySet();
		for (Object obj : set2) {
			Map.Entry entry = (Map.Entry) obj;
			// System.out.println(entry.getKey() + "---->" + entry.getValue());
			System.out.println(entry);
		}
	}

	/*
	 * Map 的常用实现类 HashMap 及主要方法的使用:
	 * //添加、删除操作
	 * Object put(Object key,Object value):向 Map 中添加一个元素
	 * Object remove(Object key): 按照指定的 key 删除此 key-value
	 * void putAll(Map t):将一个新的元素添加进来
	 * void clear():清空
	 *
	 * //元素查询的操作
	 * Object get(Object key):获取指定 key 的 value 值。若无此 key,则返回 null
	 * boolean containsKey(Object key)://判断是否包含 key 的值
	 * boolean containsValue(Object value)://判断是否包含 value 的值
	 * int size():返回集合的长度
	 * boolean isEmpty():
	 * boolean equals(Object obj)
	 * 
	 * HashMap:
	 * 1.key 是用 Set 来存放的,不可重复。value 是用 Collection 来存放的,可重复
	 * 一个 key-value 对,是一个 Entry。所有的 Entry 是用 Set 存放的,也是不可重复的。
	 * 2.向 HashMap 中添加元素时,会调用 key 所在类的 equals() 方法,判断两个 key 是否相同。若相同 则只能添加进后添加的那个元素。
	 */

	@Test
	public void test1() {
		Map map = new HashMap();
		map.put("AA", 213);
		map.put("BB", 456);
		map.put("BB", 45);
		map.put(123, "CC");
		map.put(null, null);
		map.put(new Person("DD", 23), 89);
		map.put(new Person("DD", 23), 87);
		System.out.println(map.size());
		System.out.println(map);
		map.remove("BB");
		System.out.println(map);
		Object value = map.get(1234);
		System.out.println(value);
	}
}

代码二:

package thirteen;

public class Person implements Comparable{
	private String name;
	private Integer age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Person() {
		super();
	}
	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	//static int init = 1000;
	@Override
	public int hashCode() {//return age.hashCode() + name.hashCode();没下述的健壮性好。
		final int prime = 31;
		int result = 1;
		result = prime * result + ((age == null) ? 0 : age.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
		//return init++;//不能这样用
	}

	@Override
	public boolean equals(Object obj) {//重写equals
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age == null) {
			if (other.age != null)
				return false;
		} else if (!age.equals(other.age))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	//当向TreeSet中添加Person类的对象时,依据此方法,确定按照哪个属性排列。
	@Override
	public int compareTo(Object o) {
		if(o instanceof Person){
			Person p = (Person)o;
			//return this.name.compareTo(p.name);
			//return -this.age.compareTo(p.age);//从大到小
			int i = this.age.compareTo(p.age);
			if(i == 0){
				return this.name.compareTo(p.name);
			}else{
				return i;
			}
		}
		return 0;
	}
}

代码三:

package thirteen;

public class Customer {
	private String name;
	private Integer id;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Customer(String name, Integer id) {
		super();
		this.name = name;
		this.id = id;
	}
	public Customer() {
		super();
	}
	@Override
	public String toString() {
		return "Customer [name=" + name + ", id=" + id + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		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;
		Customer other = (Customer) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}

韧桂 2020-01-02