7 LinkedHashMap
7.1 特点
1, LinkedHashMap是HashMap的子类(Map接口的子实现)
2, LinkedHashMap 基本上完全复用了HashMap的底层机构
3, (数组+链表 + 红黑树)
4, 只有一个地方做了改变(基于HashMap), 结点类型
(HashMap中存储的是Node 结点, 包含四个参数; key, value, hash, next)
(LinkedHashMap中存储的结点, 是HashMap结点的子类,在hash, key, value, next的基础上增加了两个参数, before, after, 用来保证添加顺序)
LinkedHashMap这HashMap的基础上额外维护了一个双向链表
5, LinkedHashMap由于维护了一个双向链表, 保证了迭代顺序, 所以我们认为LinkedHashMap是有序的
注意: LinkedHashMap 仅仅比HashMap的结点类型增加了前后指向, 别的东西没变
7.3 构造方法
7.4 API
8 TreeMap
8.1 特点
1, TreeMap 是Map的一个具体子实现
2, TreeMap 的数据结构是 红黑树(特殊的二叉搜索树)
3, 底层是链表
4, 大小有序
5, 不允许重复的key
6, 不允许存储null key
7, 线程不安全的
由于TreeMap底层是一个红黑树, 红黑树又是一个特殊的二叉搜索树, 那么我们要求存储到TreeMap中的key’是可以比较大小的, 大小的比较方式有两个
1, TreeMap本身提供了比较器
2,Key的类本身实现了Comparable的compareTo方法
方法1:
public class DemoTreeMap02 {
public static void main(String[] args) {
TreeMap<User, String> treeMap = new TreeMap<>(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
// String自身已经实现compareTo方法了
int cmp = o1.compareTo(o2);
cmp = cmp == 0 ? o1.age - o2.age : cmp;
return cmp;
}
});
treeMap.put(new User("zs", 18), "20");
treeMap.put(new User("ls", 10), "90");
System.out.println(treeMap);
Comparator<? super User> comparator = treeMap.comparator();
TreeMap<User, String> treeMap1 = new TreeMap<>(comparator);
treeMap1.put(new User("LGD", 18), "20");
treeMap1.put(new User("RNG", 10), "90");
System.out.println(treeMap1);
}
}
class User2 {
String name;
int age;
public User2() {
}
public User2(String name, int age) {
this.name = name;
this.age = age;
}
}
package treeMap;
import java.util.TreeMap;
public class DemoTreeMap01 {
public static void main(String[] args) {
TreeMap<User, String> treeMap = new TreeMap<>();
// User没有实现Comparable接口的时候,会报错,treeMap.User cannot be cast to java.lang.Comparable
// treeMap.put(new User("zs", 18), "20");
treeMap.put(new User("zs", 18), "20");
treeMap.put(new User("ls", 10), "90");
System.out.println(treeMap);
}
}
class User implements Comparable<User>{
String name;
int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(User o) {
int cmp = name.compareTo(o.name);
cmp = cmp==0 ? age-o.age : cmp;
return cmp;
}
}
8.2 构造方法
8.3 API
太多了,文档自己看吧,大多数都没什么用
9 Hashtable
9.1 Hashtable的特点
1, 是Map接口一个子实现
2, Hashtable是jdk1.0时候产生, Map接口是jdk1.2的时候产生
3, 底层结构 : 数组 + 链表, (和jdk1.8之前的HashMap一样)
4, 默认的初始容量11, 扩容机制: 扩为原本的2倍+1
5, 无序, 不允许重复key
6, 不允许存储null 键, 也不允许存储null值
7, 线程安全,所以效率更低
Hashtable计算hash值和计算下标的方式也不同于HashMap
6 Properties
用来做持久化的.
持久化: 内存 写到 磁盘文件上
他是Hashtable的一个子类
游戏开发不基于系统,而是基于游戏引擎, 游戏当中某些配置可能会写在配置文件中
//TODO:千万不要把info.setProperty()放在info.store()的后面,我差点被搞死
info.setProperty("count", count + "");
info.store(output, " ");
Utils类:工具类
Bean类:现实中东西的抽象类
10. Set
Map: HashMap LinkedHashMap TreeMap
Set: HashSet LinkedHashSet TreeSet
10.1 特点
1, Set这个接口是Collection的一个子接口
2, 描述的数据结构是集合
3, 有些子实现是有序的(LinkedHashSet, TreeSet), 有些子实现是无序的(HashSet)
4, 有些子实现允许存储null, 而有些子实现不允许存储null
5, 不允许存储重复元素
10.2 API
11 HashSet
11.1 构造方法
1, HashSet是Set接口的一个具体实现
2, HashSet底层持有一个HashMap对象(数组 + 链表 + 红黑树)
3, HashSet存储的元素, 实际上是存储到底层HashMap, 作为key存在
HashSet存储元素的特点, 基本上和HashMap 的key的特点一样
4, 线程不安全
11.2 API
12 LinkedHashSet
12.1 特点
1, Set接口的一个具体实现, HashSet一个子类
2, 底层持有的是一个LinkedHashMap对象, (数组 + 链表+ 红黑树, 双向链表)结构
3, 存储到LinkedHashSet中元素的特点, 基本上和LinkedHashMap中key值的特点一样
(有序的)
4, 不允许重复元素, 允许null
5, 线程不安全
12.2 构造方法
12.3 API
和HashMap是一致的
13 TreeSet
1, TreeSet 是Set接口一个具体实现
2, 底层持有的是一个TreeMap
3, 底层结构是: 红黑树
4, TreeSet存储元素的特点, 和TreeMap存储key的特点是一样的.
5, 线程不安全
13.2 构造方法
13.3 API
看文档
作业
请设计一个猜数字小游戏,可以试玩5次。试玩结束之后,给出提示:游戏试玩结束,
请付费。(要求即使把程序重启也总共只能猜5次)
(Properties: 读取和存文件记录猜数字次数)
public class Demo01 {
public static void main(String[] args) {
Properties info = new Properties();
FileInputStream input;
int count;
try {
input = new FileInputStream("game.properties");
info.load(input);
count = Integer.parseInt(info.getProperty("count"));
if(count < 5){
GuessNumber.gameStarts(info);
}else System.out.println("试玩已经结束,请付费后再继续!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
class GuessNumber {
public static void gameStarts( Properties info) throws IOException {
Random random = new Random();
int number = random.nextInt(1000);
Scanner sc = new Scanner(System.in);
int guess;
int count = Integer.parseInt(info.getProperty("count"));
FileOutputStream output = new FileOutputStream("game.properties");
while (count < 5) {
System.out.print("请输入您猜测的数字:");
guess = sc.nextInt();
if (guess == number) {
System.out.println("您猜对了!");
count++;
info.setProperty("count", count + "");
info.store(output, " ");
return;
}
// 没有猜对
else {
if (number > guess)
System.out.println("您猜小了,请重新猜测!");
else System.out.println("您猜大了, 请重新猜测!");
// 将新count写回配置文件
count++;
//TODO:千万不要把info.setProperty()放在info.store()的后面,我差点被搞死
info.setProperty("count", count + "");
info.store(output, " ");
}
}
System.out.println("试玩已经结束,请付费后再继续!");
}
}