HashMap
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
HashMap
:是基于哈希表的Map接口实现。哈希表的作用是用来保证键的唯一性的。
public class Stu {
String name;
int age;
public Stu(String name, int age) {
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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Stu stu = (Stu) o;
if (age != stu.age) return false;
return name != null ? name.equals(stu.name) : stu.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
@Override
public String toString() {
return "Stu{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
public class HashMapDemo {
public static void main(String[] args) {
Map m = new HashMap<Stu,String>();
m.put(new Stu("lili", 21),"90");
m.put(new Stu("lili", 21),"80");
m.put(new Stu("jack", 21),"100");
Set<Stu> keySet = m.keySet();
for(Stu key : keySet){
System.out.println("key="+ key.getName()+",value="+ m.get(key));
}
Set<Map.Entry<Stu,String>> entrySet = m.entrySet();
for(Map.Entry<Stu,String> me : entrySet){
System.out.println("key="+ me.getKey().getName()+",value="+me.getValue());
}
}
}
输出:
key=jack,value=100
key=lili,value=80
key=jack,value=100
key=lili,value=80
键:Student 需要实现hashCode()
、equals()
方法,保证键值唯一。
LinkedHashMap
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
LinkedHashMap
:是Map接口的哈希表和链表实现,具有可预知的迭代顺序。
- 哈希表保证键的唯一性。
- 链表保证键的有序(存储和取出的顺序一致)。
public class LinkedHashDemo {
public static void main(String[] args) {
Map m = new LinkedHashMap<Stu,String>();
m.put(new Stu("lili", 21),"90");
m.put(new Stu("lili", 21),"80");
m.put(new Stu("jack", 21),"100");
Set<Stu> keySet = m.keySet();
for(Stu key : keySet){
System.out.println("key="+ key.getName()+",value="+ m.get(key));
}
}
}
输出:
key=lili,value=80
key=jack,value=100
LinkedHashMap可以保证存储有序。
Hashtable
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable
Hashtable
:线程安全,效率低。不允许 null 键和 null 值。
HashMap
:线程不安全,效率高。允许 null 键和 null 值。
public class HashtableDemo {
public static void main(String[] args) {
// HashMap<String, String> hm = new HashMap<String, String>();
Hashtable<String, String> hm = new Hashtable<String, String>();
hm.put("it001", "hello");
// hm.put(null, "world"); //NullPointerException
// hm.put("java", null); // NullPointerException
System.out.println(hm);
}
}
TreeMap
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable
HashMap
:是基于红黑树的Map接口的实现。
- 保证元素排列方式:
- 1、自然排序(元素具备比较性):元素所属的类实现
Comparable
接口。 - 2、比较器排序(集合具备比较性):集合构造方法接收
Comparator
的实现类对象。
- 1、自然排序(元素具备比较性):元素所属的类实现
小知识:TreeMap没有直接实现Map接口。
自然排序
public class Stu implements Comparable{
String name;
int age;
public Stu(String name, int age) {
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 int compareTo(Object obj) {
Stu stu = (Stu) obj;
int num1 = this.getName().compareTo(stu.getName());
int num2 = num1 == 0 ? this.getAge() - stu.getAge() : num1;
return num2;
}
@Override
public String toString() {
return "Stu{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
public class TreeMapDemo {
public static void main(String[] args) {
// 创建集合对象
TreeMap<Stu, String> tm = new TreeMap<Stu, String>();
// 创建元素并添加元素
tm.put(new Stu("lili", 21),"90");
tm.put(new Stu("lili", 21),"80");
tm.put(new Stu("jack", 21),"100");
// 遍历集合
Set<Stu> keySet = tm.keySet();
for(Stu key : keySet){
System.out.println("key="+ key.getName()+",value="+ tm.get(key));
}
}
}
输出:
key=jack,value=100
key=lili,value=80
比较器排序
public class Stu{
String name;
int age;
public Stu(String name, int age) {
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 "Stu{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
public class TreeMapDemo {
public static void main(String[] args) {
// 创建集合对象
TreeMap<Stu, String> tm = new TreeMap<Stu, String>(new Comparator<Stu>() {
@Override
public int compare(Stu stu, Stu t1) {
int num1 = stu.getName().compareTo(t1.getName());
int num2 = num1 == 0 ? stu.getAge() - t1.getAge() : num1;
return num2;
}
});
// 创建元素并添加元素
tm.put(new Stu("lili", 21),"90");
tm.put(new Stu("lili", 21),"80");
tm.put(new Stu("jack", 21),"100");
// 遍历集合
Set<Stu> keySet = tm.keySet();
for(Stu key : keySet){
System.out.println("key="+ key.getName()+",value="+ tm.get(key));
}
}
}
输出:
key=jack,value=100
key=lili,value=80
需求:“aababcabcdabcde”,获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
思路:遍历输入的字符串,然后逐词查询集合是否为null,如果返回null,往HashMap添加;如果返回非空,该字符对应个数加一,然后再添加(修改);
public class HashMapTest {
public static void main(String[] args) {
// 定义一个字符串(可以改进为键盘录入)
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
// 定义一个TreeMap集合
TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
//把字符串转换为字符数组
char[] chs = line.toCharArray();
//遍历字符数组,得到每一个字符
for(char ch : chs){
//拿刚才得到的字符作为键到集合中去找值,看返回值
Integer i = tm.get(ch);
//是null:说明该键不存在,就把该字符作为键,1作为值存储
if(i == null){
tm.put(ch, 1);
}else {
//不是null:说明该键存在,就把值加1,然后重写存储该键和值
i++;
tm.put(ch,i);
}
}
//定义字符串缓冲区变量
StringBuilder sb= new StringBuilder();
//遍历集合,得到键和值,进行按照要求拼接
Set<Character> set = tm.keySet();
for(Character key : set){
Integer value = tm.get(key);
sb.append(key).append("(").append(value).append(")");
}
//把字符串缓冲区转换为字符串输出
String result = sb.toString();
System.out.println("result:"+result);
}
}
输出:
请输入一个字符串:
aababcabcdabcde
result:a(5)b(4)c(3)d(2)e(1)
利用put()
方法两个功能:1、添加元素不存在,直接添加;2、添加元素存在,替换原先值,并且返回原先值。