HashMap是Map里面的实现类.
HahMap没有什么需要额外学些方法,直接用Map里的方法就可以了.
HashMap的特点由键决定,它的底层原理和HashSet相同,都是哈希表结构,所以它的键也有如下特点:无序,零索引,不重复(再次强调值可以重复).
HashMap通过equals()方法与hashCode()方法保证键的唯一(关于这两个方法和哈希表的结构详见HashSet方法),如果存储的是自定义对象,需要对这两个方法进行重写,但是值如果存的是自定义对象,不需要重写.
其实Map系列都一个样,值可以重复,键不可以重复.
通过一个小练习加深印象,我们可以用HashMap系列集合进行统计.
//数组中有四种数据,随机这个数组八十次,把数据加到集合里.
String [] arr ={"A","B","C","D"};
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 80; i++) {
int j = r.nextInt(4);
list.add(arr[j]);
}
//创建HashMap;
HashMap<String ,Integer> hm = new HashMap<>();
//遍历集合得到每一个元素,再将元素与hm中的元素进行判断
for (int i = 0; i < list.size(); i++) {
//如果包含这个元素,就将原先的值加一,意思是出现的次数多了一次
if(hm.containsKey(list.get(i))){
int count = hm.get(list.get(i));
count++;
hm.put(list.get(i),count);
}
//如果不包含就将数据加入HashMap;
else{
hm.put(list.get(i),1);
}
}
//从map中获得键对应的值(数据出现的次数),再给这些值比个大小,得到出现最多次的元素的次数
int max = 0;
Set<Map.Entry<String, Integer>> entries = hm.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
Integer count = entry.getValue();
max = max>=count?max:count;
System.out.println(entry.getKey()+"="+entry.getValue());
}
//通过值寻找键,打印出现次数最多的键,由于我在这里用的是匿名内部类,所以要给变量加上final才可以正常访问
final int max1 = max;
hm.forEach((string, integer)-> {
if(integer == max1){
System.out.println("出现最多次的元素时:"+string); }
}
);
LinkedHashMap
由键做决定:有序(元素存取一致),无索引,不重复.
底层仍是哈希表,只是每个entry元素额外多了一个双链表机制记录存储的顺序,遍历按照双链表机制顺序.其实和LinkedHashSet差不多.
TreeMap
1.底层和TreeSet一样,都是红黑树结构,增删改查性能好.
2.由键决定特性:无索引,不重复,可排序(对键进行排序)
3.默认从小到大,也可以自己规定排序规则.
排序规则与TreeSet一致,都是两种方法:1.用Comparable接口制定比较规则.
2.用comparator比较器对象,指定比较规则.
注意,如果两种比较规则都存在的话用第二种,第二种方法适用于系统已经给该类定好了比较规则,但是定好的规则不满足排序需求的时候使用.
第一种排序规则,在类中实现一个Comparable接口,然后重写compareTo方法.
第二种代码如下:
//第二种排序规则
TreeMap<Integer,String> tm = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
这里我们可以学习一种新的统计思想,用map系列进行排序.上面已经用了HashMap进行统计,现在再用TreeMap进行一次统计练习.
//创建一个字符串
String s = "wqerrwqerwqrerwqrerqwerwqrerwqrerwqrerqwerwqreqwe";
//创建一个TreeMap集合,这里我想让集合按照字符在ASCII码表的大小顺序遍历,所以用TreeMap
TreeMap<Character,Integer> tm = new TreeMap<>();
//获取集合中所有的entry元素.
Set<Map.Entry<Character, Integer>> entries = tm.entrySet();
//遍历数组得到每一个字符
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
//对字符进行判断,如果字符存在于集合,那么就将字符(键)对应的值加1(字符出现了一次);
if (tm.containsKey(c)){
Integer count = tm.get(c);
count++;
tm.put(c,count);
//如果字符没有出现就将其添加
} else{
tm.put(c,1);
}
}
//遍历一下,这里巩固练习,其实直接打印出来也可以
entries.forEach(new Consumer<Map.Entry<Character, Integer>>() {
@Override
public void accept(Map.Entry<Character, Integer> entry) {
Character key = entry.getKey();
Integer value = entry.getValue();
}
});
关于使用这两种集合进行统计,如果对结果无排序要求用HashMap(效率高),如果有排序要求那么用TreeMap.