学习笔记之JavaSE(35)--JavaAPI详解10

今天学习的内容是集合类之HashMap、LinkedHashMap和TreeMap


常用的映射有HashMap、LinkedHashMap和TreeMap,下面分别介绍一下它们


一、HashMap和LinkedHashMap

HashMap、LinkedHashMap与HashSet、LinkedHashSet的原理基本相同,把映射中的键视作集中的元素即可注意HashMap的键和值都可以是null


补充个知识点:HashTable,此类也实现了Map接口,与HashMap类似,区别在于它是同步的,且不能使用null作为键和值面试要点)。虽然这个类已经过时,但是它的子类Properties很重要,可以和IO技术相结合存储键值对型的配置文件的信息


示例程序:

public class Test60 {

	public static void main(String[] args) {

		// HashMap的键不能重复,且元素是无序的
		Map<Person, String> hs = new HashMap<>();
		hs.put(new Person("张三", 21), "云南");
		hs.put(new Person("张三", 21), "北京");
		hs.put(new Person("李四", 25), "上海");
		hs.put(new Person("王五", 27), "天津");
		hs.put(new Person("赵六", 24), "广州");
		System.out.println(hs);// HashMap是无序的 {Person [name=王五, age=21]=天津,
								// Person [name=赵六, age=24]=广州, Person [name=张三,
								// age=21]=北京, Person [name=李四, age=22]=上海}

		// LinkedHashMap是有序的
		Map<Person, String> lhs = new LinkedHashMap<>();
		lhs.put(new Person("张三", 21), "云南");
		lhs.put(new Person("张三", 21), "北京");
		lhs.put(new Person("李四", 25), "上海");
		lhs.put(new Person("王五", 27), "天津");
		lhs.put(new Person("赵六", 24), "广州");
		System.out.println(lhs);// LinkedHashMap是有序的 {Person [name=张三,
								// age=21]=北京, Person [name=李四, age=25]=上海,
								// Person [name=王五, age=27]=天津, Person [name=赵六,
								// age=24]=广州}
	}
}

//要覆盖Person的hashCode()与equals()方法 
class Person {

	private String name;
	private int age;

	public Person() {
		super();
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	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 String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int hashCode() { // 覆盖Object的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) {// 覆盖Object的equals()方法
		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;
	}

}

二、TreeMap

TreeMap与TreeSet的原理也基本相同。注意由于TreeMap要根据键按照指定规则进行排序,所以TreeMap存储的元素的键不能是null,而值可以是null


示例程序:

public class Test61 {
	public static void main(String[] args) {

		// 使用自然排序
		Map<Person, String> tm = new TreeMap<>();
		tm.put(new Person("zhangsan", 21), "天津");
		tm.put(new Person("lisi", 22), "北京");// 如果Person类没有实现Comparable接口,会发生ClassCastException
		tm.put(new Person("wangwua", 23), "云南");
		tm.put(new Person("wangwub", 23), "上海");
		tm.put(new Person("zhaoliu", 24), "广州");
		System.out.println(tm);// {Person [name=zhangsan, age=21]=天津, Person
								// [name=lisi, age=22]=北京, Person [name=wangwua,
								// age=23]=云南, Person [name=wangwub, age=23]=上海,
								// Person [name=zhaoliu, age=24]=广州}

		// 使用比较器排序
		Map<Person, String> tm_com = new TreeMap<>(new ComparatorByName());
		tm_com.put(new Person("zhangsan", 21), "天津");
		tm_com.put(new Person("lisi", 22), "北京");
		tm_com.put(new Person("wangwua", 23), "云南");
		tm_com.put(new Person("wangwub", 23), "上海");
		tm_com.put(new Person("zhaoliu", 24), "广州");
		System.out.println(tm_com);// {Person [name=lisi, age=22]=北京, Person
									// [name=wangwua, age=23]=云南, Person
									// [name=wangwub, age=23]=上海, Person
									// [name=zhangsan, age=21]=天津, Person
									// [name=zhaoliu, age=24]=广州}

	}
}

class Person implements Comparable<Person> {

	private String name;
	private int age;

	public Person() {
		super();
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	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 String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int hashCode() { // 覆盖Object的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) {// 覆盖Object的equals()方法
		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;
	}

	// 本例中按照年龄进行从小到大排序,如果年龄相等,再按照姓名进行自然排序
	@Override
	public int compareTo(Person o) {

		int temp = this.age - o.age;
		return temp == 0 ? this.name.compareTo(o.name) : temp;
	}
}

// 自定义比较器,按照姓名进行自然排序,如果姓名相同,再按照年龄大小进行排序
class ComparatorByName implements Comparator<Person> {

	@Override
	public int compare(Person o1, Person o2) {

		int temp = o1.getName().compareTo(o2.getName());
		return temp == 0 ? o1.getAge() - o2.getAge() : temp;
	}
}


总结:如果要按照特定规则对元素进行排序,建议使用TreeMap;如果想让元素按照添加顺序排序,建议使用LinkedHashMap;其他情况都使用HashMap

面试题:

1.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值