目录
Class TreeMap<K,V>
查看API文档我们知道:
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable一个红黑树基于NavigableMap实现。 该地图是根据排序natural ordering其密钥,或通过Comparator在地图创建时提供,这取决于所使用的构造方法。
此实现提供了保证的log(n)时间成本
containsKey
,get
,put
和remove
操作。 算法是Cormen,Leiserson和Rivest的算法介绍中的算法的适应性 。请注意,如果这个排序的映射要正确地实现
Map
接口,那么由树映射维护的排序(如任何排序的映射)以及是否提供显式比较器都必须与equals
Map
一致。 (参见Comparable
或Comparator
为一致的精确定义与equals)。这是因为该Map
接口在来定义equals
的操作,但一个排序映射使用它所有的键比较compareTo
(或compare
)方法,于是两个从排序图的角度来说,通过该方法认为相等的键是相等的。 排序地图的行为是明确定义的,即使其排序与equals
; 它只是没有遵守Map
界面的总体合同。请注意,此实现不同步。 如果多个线程同时访问映射,并且至少一个线程在结构上修改映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅改变与现有密钥相关联的值不是结构修改。)这通常通过对自然封装映射的一些对象进行同步来实现。 如果没有这样的对象存在,应该使用Collections.synchronizedSortedMap方法“包装”地图。 这最好在创建时完成,以防止意外的不同步访问地图:
SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));由这个类的“集合视图方法”返回的
iterator
方法返回的迭代器是故障快速的 :如果映射在迭代器创建之后的任何时间被结构地修改,除了通过迭代器自己的remove
方法,迭代器会抛出一个ConcurrentModificationException 。 因此,面对并发修改,迭代器将快速而干净地失败,而不是在未来未确定的时间冒着任意的非确定性行为。请注意,迭代器的故障快速行为无法保证,因为一般来说,在不同步并发修改的情况下,无法做出任何硬性保证。 失败快速的迭代器尽力投入
ConcurrentModificationException
。 因此,编写依赖于此异常的程序的正确性将是错误的:迭代器的故障快速行为应仅用于检测错误。通过此类中的方法返回的所有
Map.Entry
对,其视图表示生成时映射的快照。 他们不支持Entry.setValue
方法。 (请注意,可以使用put
更改关联地图中的put
。)
TreeMap:底层数据结构是红黑树
TreeMap的遍历
遍历疾风剑豪(亚索)技能
参考代码:
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo1 {
public static void main(String[] args) {
//创建TreeMap集合对象
TreeMap<String, String> sstm = new TreeMap<>();
//添加元素到集合中
sstm.put("疾风剑豪","亚索");
sstm.put("被动技能","百折不屈");
sstm.put("Q技能","斩钢闪");
sstm.put("W技能","风之壁障");
sstm.put("E技能","踏前斩");
sstm.put("R技能","狂风绝息斩");
//遍历map集合
Set<Map.Entry<String, String>> entries = sstm.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "---" + value);
}
System.out.println("\n亚索连招EQRW");
}
}
输出结果:
E技能---踏前斩
Q技能---斩钢闪
R技能---狂风绝息斩
W技能---风之壁障
疾风剑豪---亚索
被动技能---百折不屈亚索连招EQRW
通过输出结果我们得出结论:由于TreeMap底层数据结构是红黑树,所以存储顺序和取出顺序不一定一致 。
TreeMap遍历--匿名内部类
创建Hero类:
import java.util.Objects;
public class Hero {
private String name;
private int age;
public Hero() {
}
public Hero(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 "英雄:{" +
"姓名='" + name + '\'' +
", 年龄=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Hero hero = (Hero) o;
return age == hero.age &&
Objects.equals(name, hero.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
参考代码:
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo2 {
public static void main(String[] args) {
//创建TreeMap集合对象
TreeMap<Hero, String> map = new TreeMap<> (new Comparator<Hero>() {
@Override
public int compare(Hero o1, Hero o2) {
//年龄
int h = o1.getAge() - o2.getAge();
//姓名
int h1 = h == 0 ? o1.getName().compareTo(o2.getName()) : h;
return h1;
}
});
//创建Hero对象
Hero h1 = new Hero("疾风剑豪", 24);
Hero h2 = new Hero("封魔剑魂", 28);
Hero h3 = new Hero("无极剑圣", 68);
Hero h4 = new Hero("暗裔剑魔", 1002);
Hero h5 = new Hero("无双剑姬", 16);
//添加元素到集合中
map.put(h1,"狂风绝息斩");
map.put(h2,"封尘绝念斩");
map.put(h3,"高原血统");
map.put(h4,"大灭");
map.put(h5,"无双挑战");
System.out.println("英雄联盟拿剑的英雄的大招是什么?\n");
//遍历TreeMap集合
Set<Map.Entry<Hero, String>> entries = map.entrySet();
for (Map.Entry<Hero, String> entry : entries) {
Hero key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "---" + value);
}
}
}
输出结果:
英雄联盟拿剑的英雄的大招是什么?
英雄:{姓名='无双剑姬', 年龄=16}---无双挑战
英雄:{姓名='疾风剑豪', 年龄=24}---狂风绝息斩
英雄:{姓名='封魔剑魂', 年龄=28}---封尘绝念斩
英雄:{姓名='无极剑圣', 年龄=68}---高原血统
英雄:{姓名='暗裔剑魔', 年龄=1002}---大灭
通过输出结果我们得出结论:使用匿名内部类可以对年龄进行排序,重写equals方法和hashCode方法。
这回你了解了英雄联盟拿剑的英雄有哪些了吗?
🧡🧡到底啦!给靓仔一个关注吧!🧡🧡