Properties

  • map接口实现子类
    • 1 properties类继承于 Hashtable 并且实现了map接口,也是一种使用kv对的形式来保存数据
      2 使用特点于hashtable蕾丝
      3 properties还可以用来从xxx.properties 文件中加载数据到properties类对象进行读取和修改
      4 工作后 xxx.properties 文件通常作为配置文件,这个知识点将在io溜中学到
  1. public static void main(String[] args) {
  2. Properties properties = new Properties();
  3. properties.put("1","addicated");
  4. System.out.println(properties.get("1"));
  5. // remove(key ) 进行删除
  6. properties.remove("1");
  7. properties.put("1","mengnan"); // 相同key 则修改value
  8. /*
  9. class Properties extends Hashtable<Object,Object> {
  10. 继承自hashtable
  11. kv 不得为空
  12. */
  13. // put 方法调用hashTable 的put方法。
  14. }

TreeSet

  • map接口的一个实现子类 区别于hashSet treeSet是有序的
  • 底层实际上是 TreeMap
  • 特点
    • // 1 当使用午餐构造器的时候,treeSet 仍然是无序的
      // 2 希望添加元素,按照字符串大小进行排序
      // 3 使用treeSet 提供的一个构造器,可以传入一个比较器 使用匿名内部类的方式
      // 并制定排序规则
      // 4 简单分析源码

      源码分析

      ```java public static void main(String[] args) {
  1. // 1 当死使用午餐构造器的时候,treeSet 仍然是无序的
  2. // 2 希望添加元素,按照字符串大小进行排序
  3. // 3 使用treeSet 提供的一个构造器,可以传入一个比较器 使用匿名内部类的方式
  4. // 并制定排序规则
  5. // 4 简单分析源码
  6. TreeSet treeSet = new TreeSet(new Comparator() {
  7. @Override
  8. public int compare(Object o1, Object o2) {
  9. // 下面调用string的 compareTo方法进行字符串大小比较
  10. return ((String) o1).compareTo((String) o2);
  11. }
  12. });
  13. // 添加数据
  14. treeSet.add("addicated");
  15. treeSet.add("addicated1");
  16. treeSet.add("addicated2");
  17. treeSet.add("addicated3");
  18. System.out.println(treeSet);
  19. // 构造器
  20. 无参构造器去创建对象时, treeSet其实仍然是无序的。但是底层会调用StringcompareTo方法作为比较规则来对插入进来的kv对进行排序。

public TreeSet() { this(new TreeMap()); } treeSet 底层是treeMap // 1 构造器底层会把传入的匿名比较器对象传入 赋给 treeset的底层的 treemap的属性 this.compartor

public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; }

// add 方法底层
// 这个地方的 PRESENT 实际上与hashSet中的 处理一样,作为一个常量直接插入,以key来进行区分元素重复 public boolean add(E e) { return m.put(e, PRESENT)==null; } public V put(K key, V value) { Entry t = root; if (t == null) { // 在第一次调用的时候直接吧entry元素加入, 后面再次加入的时候调用比较器比较 compare(key, key); // 传入参数为 key 其实两个参数相等,调用compare必等0 但是没有用变量去接收,也不影响下面代码的执行,只是在第一次添加元素的时候就调用一下compare检测是否为null,为null直接抛npe

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;  // cpr 实际上是构造器调用的时候传入的匿名内部类,即比较规则
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else   // 加入的值在 treeset中已经有的时候,comapre返回为0 走else 分支,
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}
     */
<a name="EDxz7"></a>
# TreeMap 

- 与hashMap的区别就是有序,且可自定义排序规则
- 大部分特性与TreeSet相同,因为二者同根同源
```java

        1 源码解读
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
        2 调用put 方法 ,
            第一次添加直接吧 k-v 封装到 entry对象 放入 root
      if (t == null) {
            compare(key, key); //  传入参数为 key  其实两个参数相等,调用compare必等0 但是没有用变量去接收,也不影响下面代码的执行,只是在第一次添加元素的时候就调用一下compare检测是否为null,为null直接抛npe
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
            第二次加入的时候启用比较器
            Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do { // 遍历所有的key  给当前的key 找适当的位置,然后挂上去
                parent = t;
                cmp = cpr.compare(key, t.key);  // 动态绑定到我们的匿名内部类的compare方法
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else   // 如果遍历过程中,发现准备添加的key 和当前已经有的key 相等 疾苦直接返回,不进行添加
                        // hashMap 取决与equals方法,treeMap取决于传入的 匿名内部类中实现的compartor方法
                        // 按照 比较方法 得到 key相等的情况则直接不进行值插入
                    return t.setValue(value);
            } while (t != null);
        }

比较规则的传入

  • 调用有参构造器 并且以匿名内部类的形式吧比较器传入即可

         // 使用默认的构造器 创建treeMap 仍然是无需的
          // 与treeSet一样,使用匿名内部类来定义比较规则
          TreeSet treeSet = new TreeSet(new Comparator() {
              @Override
              public int compare(Object o1, Object o2) {
    
                  return ((String) o1).compareTo((String) o2);
    
              }
          });
    

    比较器注意点

  • treeMap treeSet的比较器,某种程度上接近 hashMap中先比较索引值之后调用equals 比较对象内容的功用。

  • 但仍然有不同之处
    if (cpr != null) {
              do { // 遍历所有的key  给当前的key 找适当的位置,然后挂上去
                  parent = t;
                  cmp = cpr.compare(key, t.key);  // 动态绑定到我们的匿名内部类的compare方法
                  if (cmp < 0)
                      t = t.left;
                  else if (cmp > 0)
                      t = t.right;
                  else   // 如果遍历过程中,发现准备添加的key 和当前已经有的key 相等 疾苦直接返回,不进行添加
                          // hashMap 取决与equals方法,treeMap取决于传入的 匿名内部类中实现的compartor方法
                          // 按照 比较方法 得到 key相等的情况则直接不进行值插入
                      return t.setValue(value);
              } while (t != null);
          }