您的位置:首页 > 编程语言 > Java开发

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

2016-11-24 13:32 495 查看
今天学习的内容是集合类之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中对函数式编程的支持)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: