3.10 TreeSet源码解读
//1.当我们使用无参构造器,创建 TreeSet 时,仍然是无序的
//2.希望按照字符串大小来排序(如果未单独设置,类默认比较方法是从小到大)
//3.使用 TreeSet 提供的一个构造器,可以传入一个比较器(匿名内部类)
// 并指定排序规则
//4.简单看看源码//TreeSet treeSet = new TreeSet();
TreeSet treeSet = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2){//下面 调用String的 compareTo方法进行字符串大小比较//return ((String)o1).compareTo((String)o2);//如果我们需要加入的元素,按照长度大小排序return ((String)o1).length() - ((String)o2).length();}
});//添加数据
treeSet.add("jack");
treeSet.add("tom");
treeSet.add("sp");
treeSet.add("a");//treeSet.add("abc");
//而此时若是compare()按长度大小排序,加入 "and"时,该元素因为和 "tom" 长度相同加入不了/*解读1.构造器把传入的比较器对象,赋给了 TreeMap 的属性public TreeMap(Comparator<? super K> Comparator){this.comparator = comparator;}2.在调用 treeSet.add("tom"),在底层会执行到if (cpr != null) { //cpr 就是我们的匿名内部类(对象)do {parent = t;//动态绑定到我们的匿名内部类(对象)comparecmp = cpr.compare(key, t.key); if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else //如果相等,即返回0,这个Key 就没有加入return t.setValue(value);} while (t != null);}
*/
4.5 Hashtable底层结构和源码分析
Hashtable基本介绍:
- 存放的元素是键值对:即 K - V
- Hashtable 的键和值都不能为 null,否则会抛出 NullPointerException
- Hashtable 使用方法基本上和 HashMap 一样
- Hashtable 是线程安全的,HashMap 是线程不安全的
HashTable底层结构:
Hashtable table = new Hashtable();
table.put("john",100);
table.put(null, 100);//异常
table.put("john", null);//异常 NuLLPointerException
table.put("Lucy",100);//ok
table.put("uic",100);
table.put("uic",88);//替换//1.底层有数组 Hashtable$Entry[] 初始化大小为 11
//2.临界值 threshold = 数组大小 * 0.75
//3.扩容:按自己的机制
HashTable扩容机制:
/*
4.执行方法 addEntry(hash, key value, index);添加K-V封装到Entry
5.当 if(count >= threshold) 满足时就进行扩容
6.按照 int newCapacity = (oldCapacity << 1) + 1 的大小扩容,即 原大小* 2 + 1
*/
HashTable 和 HashMap 对比:
| 版本 | 线程安全(同步) | 效率 | 允许 null键 null值 | |
|---|---|---|---|---|
| HashMap | 1.2 | 不安全 | 高 | 可以 |
| Hashtable | 1.0 | 安全 | 较低 | 不可以 |
4.6 Properties底层结构和源码分析
Properties 基本介绍:
- Properties类继承自 Hashtable 类并且实现了 Map 接口,也是使用一种键值对的形式来保存数据。
- 他的使用特点和Hashtable类似
- Properties 还可以用于从 xxx-properties文件中,加载数据到 Properties类对象。并进行读取和修改
- 说明:工作后 xxx-properties 文件通常作为配置文件,这个知识点在IO流举例。有兴趣可先看文章
Properties 基本使用:
//解读:
//1.Properties类继承自 Hashtable
//2.可以通过 k-v 存放数据,当然 key 和 value 不能为空//增加
Properties properties = new Properties();
properties.put("john",100);
properties.put( null, 100);//抛出异常
properties.put("john", null);//抛出异常
properties.put("lucy", 100);
properties.put("lic",100);
properties.put("lic", 88);//如果有相同的键,值会被替换
System.out.println(properties);//删除
properties.remove("lic");//改
properties.put("john",“北京大学”);
System.out.println(properties);//查
System.out.println(properties.get("john"));
System.out.println(properties.getProperty("john"));
4.7 TreeMap
//使用默认的构造器,创建TreeMap,是无序的(也没有排序)
/*要求:按照传入的 k(String) 的大小进行排序
*/
//TreeMap treeMap = new TreeMap();
TreeMap treeMap = new TreeMap(new Comparator(){@Overridepublic int compare(Object o1, Object o2){//按照传入的 k(String) 的大小进行排序//return ((String) o1).compareTo((String) o2);//按照K(String)的长度大小排序return ((String) o1).length() - ((String)o2).length();}
});
treeMap.put("jack","杰克");
treeMap.put("tom","汤姆");
treeMap.put("kristina","克瑞斯提诺");
treeMap.put("smith","史密斯");treeMap.put("hsp","一盒");//如果当前依照长度大小排序,该key和tom长度大小相同,键视为同一个,"一盒"会替换"汤姆"/*解读:1.构造器,把传入的实现了 Comparator 借口的匿名内部类(对象),传给TreeMap的comparatorpublic TreeMap(Comparator<? super K> Comparator){this.comparator = comparator;}2.调用 put方法2.1 第一次添加,把 k-v 封装到 Entry 对象,放到rootEntry<K,V> t = root;if (t == null){compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}2.2 以后添加Comparator<? super K> cpr = comparator;if (cpr != null) {do{ //遍历所有key,给当前的 key 找适当的位置parent = t;cmp = cpr.compare(key, t.key); //动态绑定到匿名内部类的compareif (cmp < 0)t =t.left;else if (cmp >0)t =t.right;else //如果遍历过程中,发现准备添加的 key,和当前已有的 key 相等,就不添加return t.setValue(value);} while (t != null);}
*/
五、集合选型规则
在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择,分析如下:
-
先判断存储的类型(一组对象 [ 单列 ] 或一组键值对 [ 双列 ] )
-
一组对象:Collection接口
- 允许重复:List
增删多:LinkedList[底层维护了一个双向链表]
改查多:ArrayList[底层维护 Object类型的可变数
- 不允许重复:Set
无序:HashSet[底层是HashMap,维护了一个哈希表 即(数组+链表+红黑树)]
排序:TreeSet
插入和取出顺序一致:LinkedHashSet,维护数组+双向链表
-
一组键值对Map
-
键无序:HashMap [ 底层是:哈希表 jdk7:数组+链表;jdk8:数组+链表+红黑树 ]
-
键排序:TreeMap
-
键插入和取出顺序一致:LinkedHashMap
-
读取文件 Properties
-
六、Collections工具类
Collections工具类介绍
-
Collections 是一个操作 Set、List 和 Map 等集合的工具类
-
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作
排序操作:(均为static方法)
//创建ArrayList 集合,进行测试
List list = new ArrayList();
list.add("tom");
list.add("simth");
list.add("king");
-
reverse ( List ) :反转 List 中元素的顺序
-
shuffle ( List ) :对 List 集合元素进行随机排序
-
sort ( List ) :根据元素的自然顺序对指定 List 集合元素按升序排序
-
sort ( List, Comparator ) :根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
//sort(List, Comparator):根据指定的 Comparator 产生的顺序对List集合元素 //我们希望按照字符串的长度大小排序 Collections.sort(list, new Comparator(){@Overridepublic int compare(Object o1, Object o2) {//可以加入校验代码return ((String)o2).Length() - ((String)o1).Length(); } -
swap ( List, int,int ) :将指定 list 集合中的 i 处元素和 j 处元素进行交换## 六、
查找、替换
-
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
System.out.println( Collectios.max(list) ); -
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Collections.max(list, new Comparator(){@Overridepublic int compare(Object o1, Object o2) {//可以加入校验代码return ((String)o2).Length() - ((String)o1).Length(); } -
Object min(Collection)
-
Object min(Collection, Comparator)
-
int frequency(Collection, Object):返回指定集合中指定元素的出现次数
-
void copy(List dest, List src):将src中的内容复制到dest中
- 为了完成一个完整拷贝,需要先给新集合赋值,大小和原集合一样
-
boolean replaceAll ( List list, Object oldVal, Object newVal ) :使用新值替换 List对象的所有旧值
