学习笔记之JavaSE(35)--JavaAPI详解10
2016-11-24 13:32
495 查看
今天学习的内容是集合类之HashMap、LinkedHashMap和TreeMap
常用的映射有HashMap、LinkedHashMap和TreeMap,下面分别介绍一下它们
补充个知识点:HashTable,此类也实现了Map接口,与HashMap类似,区别在于它是同步的,且不能使用null作为键和值(面试要点)。虽然这个类已经过时,但是它的子类Properties很重要,可以和IO技术相结合存储键值对型的配置文件的信息。
示例程序:
示例程序:
总结:如果要按照特定规则对元素进行排序,建议使用TreeMap;如果想让元素按照添加顺序排序,建议使用LinkedHashMap;其他情况都使用HashMap
面试题:
1.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。
常用的映射有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中对函数式编程的支持)。
相关文章推荐
- 学习笔记之JavaSE(31)--JavaAPI详解6
- 学习笔记之JavaSE(27)--JavaAPI详解2
- 学习笔记之JavaSE(34)--JavaAPI详解9
- 学习笔记之JavaSE(29)--JavaAPI详解4
- IOS学习笔记10—UIControl对象详解
- 学习笔记之JavaSE(10)--面向对象编程1
- [置顶] JavaSE学习笔记_10:Java多线程
- live555学习笔记10-h264 RTP传输详解(2)
- 【深度学习】笔记4_caffe第二个比较经典的[小图片]识别例子CIFAR_10的运行,网络模型的详解
- IOS学习笔记10—UIControl对象详解
- Spark Hadoop集群部署与Spark操作HDFS运行详解---Spark学习笔记10
- 学习笔记_JavaSE_10_Java面向对象04
- live555学习笔记10-h264 RTP传输详解(2)
- 学习笔记之JavaSE(19)--面向对象编程10
- 学习笔记之JavaSE(28)--JavaAPI详解3
- (转)live555学习笔记10-h264 RTP传输详解(2)
- 学习笔记之JavaSE(30)--JavaAPI详解5
- spring学习笔记(10)@AspectJ研磨分析[3]增强织入顺序实例详解
- iOS学习笔记10- IOS MagicRecord 详解
- Spark Hadoop集群部署与Spark操作HDFS运行详解---Spark学习笔记10