Collection

声明:以下笔记来源于韩顺平视频https://www.bilibili.com/video/BV1fh411y7R8?p=1,笔记为楼主亲手劳动,劳动不易,转载请标明谢谢。

Collection

集合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n1bsaFQp-1648481078868)(D:\Typora Data\Img/image-20220306163403688.png)]

集合的好处与理解
  • 数组
    1. 长度开始时必须指定,而且一旦指定, 不能更改
    2. 保存的必须为同一类型的元素
    3. 使用数组进行增加元素的示意代码-比较麻烦
  • 集合
    1. 可以动态保存任意多个对象,使用比较方便!
    2. 提供了一系列方便的操作对象的方法: add、 remove、 set、 get等
    3. 使用集合添加,删除新元素的示意代码-简洁了
集合简介
  1. 集合主要是两组(单列集合,双列集合)
  2. ColLection接口有两个重要的子接口List Set,他们的实现 子类都是单列集合
  3. Map接口的实现子类是双列集合,存放的K-V
Collection 接口实现类的特点
  1. public interface Collection<E> extendsIterable<E>
    
  2. collection实现子类可以存放多个元素,每个元素可以是Object

  3. 有些Collection的实现类,可以存放重复的元素,有些不可以

  4. 有些Collection的实现类,有些是有序的(List),有些不是有序(Set)

  5. Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

Collection接口和常用方法(ArrayList 子类实现)
  1. add:添加单个元素

  2. remove:删除指定元素

  3. contains:查找元素是否存在

  4. size:获取元素个数

  5. isEmpty:判断是否为空

  6. clear:清空

  7. addAll:添加多个元素

  8. containsAll:查找多个元素是否都存在

  9. removeAll:删除多个元素

  10. @SuppressWarnings("all")
    public class CollectionMethods_ {
        public static void main(String[] args) {
            List list = new ArrayList();
    
            //添加单个元素
            boolean flag = list.add("jack");
            list.add(10);
            list.add(true);
    
            //删除指定元素
            boolean flag1 = list.remove("jack");
            list.remove(0);
    
            //查找元素是否存在
            boolean flag3 = list.contains(10);
    
            //获取元素个数
            System.out.println(list.size());
    
            //判断是否为空
            System.out.println(list.isEmpty());
    
            //清空
            list.clear();//void
    
            List list1 = new ArrayList();
            list1.add("老韩");
            list1.add("狂神");
            list1.add("字节跳动");
    
            //添加多个元素
            list.addAll(list1);
            System.out.println(list);
    
            //查找多个元素是否都存在
            boolean flag4 = list.containsAll(list1);
    
            //删除多个元素
            boolean flag5 = list.removeAll(list1);
        }
    }
    
    
Collection接口遍历元素方式
  1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。

  2. 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

  3. 迭代器的执行原理

    • Iterator iterator = coll.iterator(); //得到一个集合的迭代器
      //hasNext():判断是否还有下一个元素
      while(iterator.hasNext(){
      //next()作用:1.下移2.将下移以后集合位置上的元素返回
      System. out.println(iterator.next();

      }

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XW7FMY06-1648481078873)(D:\Typora Data\Img/image-20220308173705958.png)]

  4. Iterator仅用于遍历集合,Iterator 本身并不存放对象。

  5. 注意:在调用it.next(方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException。

    • public class CollectionIteration {
       public static void main(String[] args) {
           Collection col = new ArrayList();
      
           col.add(new BooK("三国演义","罗贯中",10.1));
           col.add(new BooK("小李飞刀","古龙",5.1));
           col.add(new BooK("红楼梦","曹雪芹",34.6));
      
           Iterator iterator = col.iterator();//绘制迭代器
      
           for (Object book : col) {//增强for遍历
               System.out.println(book);
           }
      
           while (iterator.hasNext()) {//迭代遍历
               Object obj = iterator.next();
               System.out.println(obj);
           }
      
           iterator = col.iterator();//重置迭代器指针(游标)
       }
      }
      
      class BooK{
       private String name;
       private String author;
       private double price;
      
       public BooK(String name, String author, double price) {
           this.name = name;
           this.author = author;
           this.price = price;
       }
      
       @Override
       public String toString() {
           return "BooK{" +
                   "name='" + name + '\'' +
                   ", author='" + author + '\'' +
                   ", price=" + price +
                   '}';
       }
      }
      
  6. 增强for遍历

      1. 增强for底层仍然是Iterator
      2. 快捷键 I (在Idea中)
    • @SuppressWarnings({"all"})
      public class CollectionFor_ {
       public static void main(String[] args) {
           Collection col = new ArrayList();
      
           col.add(new BooK("三国演义","罗贯中",10.1));
           col.add(new BooK("小李飞刀","古龙",5.1));
           col.add(new BooK("红楼梦","曹雪芹",34.6));
      
           for (Object book : col) {
               System.out.println("book=" + book);
           }
      
       }
      }
      

List

List 接口的基本介绍
  1. List 接口是Collection接口的子接口
  2. List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复
  3. List集合中的每个元素都有其对应的顺序索引,即支持索引
  4. JDK API中List接口的实现类有很多,但常用的有ArrayList,LinkedList,Vector
List 接口常用的方法
  1. void add(int index, Object ele):在index位置插入ele元素

  2. boolean addAl(int index, Collection eles):从index位置开始将eles中的所有元素添加进来

  3. Object get(int index):获取指定index位置的元素

  4. int indexOf(Object obj):返回obj在集合中首次出现的位置

  5. int lastlndexOf(object obj):返回obj在当前集合中末次出现的位置

  6. Object remove(int index):移除指定index位置的元素,并返回此元素

  7. Object set(int index, Object ele):设置指定index位置的元素为ele ,相当于是替换.

  8. List subList(int fromIndex, int tolndex): 返回从fromIndex到tolndex位置的子集合

  9. @SuppressWarnings({"all"})
    public class ListMethods_ {
     public static void main(String[] args) {
         List list = new ArrayList();
         list.add("张三丰");
         list.add("贾宝玉");
    
         //void add(int index, Object ele):在index位置插入ele元素
         list.add(1,"老天师");
    
         List list1 = new ArrayList();
         list1.add("jack");
         list1.add("tom");
         //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
         list.addAll(1,list1);
    
         //Object get(int index):获取指定index位置的元素
         System.out.println(list.get(2));
    
         //int indexOf(Object obj):返回obj在集合中首次出现的位置
         System.out.println(list.indexOf("tom"));
    
         list.add("老天师");
         //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
         System.out.println(list.lastIndexOf("老天师"));
    
         //Object remove(int index):移除指定index位置的元素,并返回此元素
         list.remove(0);
    
         //1. Object set(int index, Object ele):设置指定index位置的元素为ele ,相当于是替换.
         list.set(1,"玛丽");
    
         //List subList(int fromIndex, int tolndex):返回从fromIndex到tolndex位置的子集合
         List list2 = list.subList(1, 3);//[ , )
    
    
     }
    }
    
    
List 三种遍历方式 (Iterator 增强for 普通for)
@SuppressWarnings({"all"})
public class ListFor {
 public static void main(String[] args) {
     List list = new ArrayList();
     //      向上转型的好处
     //		List list = new Vector();
     //      List list = new LinkedList();

     list.add("jack");
     list.add("Tom");
     list.add("鱼香肉丝");
     list.add("北京烤鸭子");

     System.out.println("===迭代器遍历list===");
     Iterator iterator = list.iterator();
     while (iterator.hasNext()) {
         Object next = iterator.next();
         System.out.println(next);
     }

     System.out.println("===增强for遍历list===");
     for (Object o :list) {
         System.out.println("obj =" + o);
     }

     System.out.println("===普通for遍历list===");
     for (int i = 0; i < list.size(); i++) {
         System.out.println(list.get(i));
     }

 }
}

ArrayList

ArrayList注意事项
  1. permits all elements, including null , ArrayList可以加入null,并且多个
  2. ArrayList是由数组来实现数据存储
  3. ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.
  4. 在多线程情况下,不建议使用ArrayList
ArrayList源码分析结论
  1. ArrayList中维护了一一个Object类型的数组elementData.
  2. transient Object[] elementData; //transient表示瞬间,短暂的,表示该属性不会被序列化
  3. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0, 第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
    如果使用的是指定大小的构造器,则初始elementData容量为指定大小, 如果需要扩容,
    则直接扩容elementData为1.5倍。
ArrayList .add()方法底层扩容步骤
  1. 创建一个空的elementData数组 = {}

    • public ArrayList() {
          this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
      }
      
  2. 执行list.add()

    • 先确定是否扩容
    • 然后执行赋值
    • ensureCapacityInternal方法中如果第一次就找最小容量minCapacity10,不是则扩容。
    • modCount++记录集合被修改的次数,如果elementData的大小不够,就调用grow()去扩容
    • 在grow()中真的扩容
    • 使用扩容机制来确定要扩容到多大
    • 第一 次newCapacity =10
    • 第次及其以后,按照1.5倍扩容
    • 扩容使用的是:Arrays.copyOf()
    • 特别说明的是不同的jdk版本方法体有所修改
注意事项
  • 注意,注意,注意,Idea默认情况下,Debug显示的数据是简化后的,如果希望看到完整的数据需要做设置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Ig3kotz-1648481078875)(D:\Typora Data\Img/image-20220310092912059.png)]

  • 还有就是要自己去动手,看着会了,脑子一下记住,但很快就会忘,多动手,多回顾,东西才是自己的!!!

Vector

Vector的基本介绍
  1. Vector底层也是一 个对象数组,protected Object[] elementData;

  2. Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized

    public synchronized E get(int index) {
    	if (index >= elementCount)
    	throw new ArrayIndexOutOfBoundsException(index);
    	return elementData(index);
    
    }
    
  3. 在开发中,需要线程同步安全时,考虑使用Vector.

  4. 结构

    • public class Vector<E>
       extends AbstractList<E>
       implements List<E>, RandomAccess, Cloneable, java.io.Serializable
      {}
      
Vector 和 ArrayList的比较
底层结构版本线程安全,同步效率扩容倍数
ArrayList可变数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};jdk1.2不安全,效率高如果有参构造1.5倍如果是无参
1.第一 次10
2.从第二次开始安1.5扩容
Vector可变数组 protected Object[] elementData;jdk1.0安全,效率不高如果是无参,默认10
满后,就按2倍扩容
如果指定大小,则每次直
接按2倍扩容
//测试代码 debug使用
@SuppressWarnings({"All"})
public class Vector_ {
 public static void main(String[] args) {
     Vector vector = new Vector();
     //        Vector vector = new Vector(8);	
     for (int i = 0; i < 10; i++) {
         vector.add(i);
     }

     vector.add(100);

     System.out.println("vector =" + vector);
 }
}

LinkedList

linkedList 的全面说明
  1. LinkedList实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,没有实现同步.
  4. LinkedList底层维护了一个双向链表.
  5. LinkedList中维护了两个属性first和last分别指向首节点和尾节点
  6. 每个节点(Node对象) ,里面又维护了prev、next. item三个属性,其中通过prev指向前一个,通过next指向后一个节点。 最终实现双向链表.
  7. 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高
双向链表模拟
@SuppressWarnings({"all"})
public class LinkedList01 {
 public static void main(String[] args) {
     Node jack = new Node("jack");
     Node tom = new Node("tom");
     Node shruad = new Node("shruad");

     jack.next = tom;
     tom.next = shruad;
     shruad.pre = tom;
     tom.pre = jack;

     Node first = jack;
     Node last = shruad;
     while (true) {
         if (first == null) {
             break;
         }
         System.out.println(first);
         first = first.next;
     }

     Node swith = new Node("swith");
     tom.next = swith;
     swith.next = shruad;
     shruad.pre = swith;
     swith.pre = tom;

     System.out.println("====分界====");
     while (true) {
         if (last == null) {
             break;
         }
         System.out.println(last);
         last = last.pre;
     }

 }
}

class Node {
 public Object item;
 public Node next;
 public Node pre;

 public Node(Object item) {
     this.item = item;
 }

 @Override
 public String toString() {
     return "Node name=" + item;
 }
}
linkedList 的 CRUD
@SuppressWarnings({"all"})
public class LinkedListCRUD {
 public static void main(String[] args) {
     LinkedList linkedList = new LinkedList();
     //默认添加到尾部
     linkedList.add(1);
     linkedList.add(2);
     linkedList.add(3);



     //默认删除第一个
     linkedList.remove();
     for (Object o :linkedList) {
         System.out.println(o);
     }

     System.out.println(linkedList.get(0));//查

     linkedList.set(1,999);//改



     Iterator iterator = linkedList.iterator();
     while (iterator.hasNext()) {//迭代器遍历
         Object obj = iterator.next();
         System.out.println(obj);
     }

     for (Object o :linkedList) {//增强for遍历
         System.out.println(o);
     }

     for (int i = 0; i < linkedList.size(); i++) {//普通for遍历
         System.out.println(linkedList.get(i));
     }


 }
}
ArrayList 和 LinkedList 的比较
底层结构增删的效率查改的效率
ArrayList可变数组较低
数组扩容
较高
LinkedList双向链表较高
通过链表追加
较低

对于选择ArrayList 和 LinkedList 方面:

  1. 如果我们改查的操作多,选择ArrayList
  2. 如果我们增删的操作多,选择LinkedList
  3. 一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
  4. 在个项目中, 根据业务灵活选择,也可能这样,-个模块使用的是ArrayList,另外一个模块是LinkedList,也就是说,要根据业务来进行选择

Set

Set 接口的基本介绍
  1. 无序(添加和取出的顺序不一-致),没有索引,(不能使用索引的方式进行迭代)
  2. 不允许重复元素,所以最多包含一个null
  3. JDK API中Set接口的实现类有: HashSet,TreeSet

HashSet

HashSet 全面说明
  1. HashSet实现了Set接口

  2. HashSet实际上是HashMap

    public HashSet() {
     map = new HashMap<>();
    }
    
  3. HashSet底层是HashMap,HashMap底层是(数组+ 链表 + 红黑树)

HashSet 底层添加元素分析(hash() + equals())
  1. HashSet底层是HashMap
  2. 添加一个元素时,先得到hash值-会转成->索引值
  3. 找到存储数据表table ,看这个索引位置是否已经存放的有元素
  4. 如果没有,直接加入
  5. 如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后
  6. 在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小 >=MIN__TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
  7. size++ 不只是table表的第一个,只要增加一个对象就会增加。
  8. TREEIFY_THRESHOLD 加到8时,但MIN__TREEIFY_CAPACITY没到64之前,还是会加到对应链表的后面,不会在另一条链表加,因为hash值对应的是那个table[i]的位置
HashSet 练习题
  1. 创建3个Employee对象放入HashSet中

  2. 当name和age的值相同时,认为是相同员工,不能添加到HashSet集合中

  3. public class HashSetExercise_ {
     public static void main(String[] args) {
         HashSet hashSet = new HashSet();
         hashSet.add(new Employee("milan",18));
         hashSet.add(new Employee("smith",28));
         hashSet.add(new Employee("milan",18));
    
         System.out.println("hashSet = " +  hashSet);
     }
    }
    
    class Employee {
     private String name;
     private int age;
    
     public Employee(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 boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         Employee employee = (Employee) o;
         return age == employee.age &&
                 Objects.equals(name, employee.name);
     }
    
     @Override
     public int hashCode() {
         return Objects.hash(name, age);
     }
    
     @Override
     public String toString() {
         return "Employee{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
     }
    }
    

LinkedHashSet

LinkedHashSet (父类是HashSet)
  1. 在LinkedHastSet中维护了一个hash表和双向链表( LinkedHashSet有head和tail )
  2. 每一个节点有 before 和after属性,这样可以形成双向链表
  3. 在添加一个元素时,先求hash值,在求索引.确定该元素在hashtable的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和hashset-样])
  4. 这样的话,我们遍历LinkedHashSet也能确保插入顺序和遍历顺序一致

Map

Map接口说明
  1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value

  2. Map中的key和value 可以是任何引用类型的数据,会封装到HashMap$Node对象中

  3. Map中的key不允许重复,原因和HashSet -一样,前面分析过源码.

  4. Map中的value可以重复

  5. Map的key可以为null, value也可以为null,注意key为null,只能有一个,value为null ,可以多个.

  6. 常用String类作为Map的key

  7. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value

  8. Map存放数据的key-value,一对k-v是放在一个Node中的,有因为Node实现了Entry 接口,有些书上也说一-对k-v就是-个Entry(Map.Entry>>Node)

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8JKLvI38-1648481078878)(D:\Typora Data\Img\image-20220306172147294.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EkoaBtch-1648481078878)(D:\Typora Data\Img\image-20220306163452566.png)]

Map接口常用方法
  1. put:添加
  2. remove:根据键删除映射关系
  3. get:根据键获取值
  4. size:获取元素个数
  5. isEmpty:判断个数是否为0
  6. clear:清除
  7. containsKey:查找键是否存在
Map遍历
  1. containsKey:查找键是否存在
  2. keySet:获取所有的键
  3. entrySet:获取所有关系k-v
  4. values:获取所有的值
@SuppressWarnings({"all"})
public class MapFor_ {
 public static void main(String[] args) {
     //Map 的六大遍历方式
     HashMap map = new HashMap();
     map.put("邓超","孙俪");
     map.put("王宝强","马蓉");
     map.put("宋喆","马蓉");
     map.put("刘令博",null);
     map.put(null,"刘亦菲");
     map. put("鹿晗","关晓彤");

     //第一种   KeySet

     Set keySet = map.keySet();
     System.out.println("======第一种方式增强for map.keySet()======");
     for (Object key :keySet) {
         System.out.println(key + "=" + map.get(key));
     }

     System.out.println("======第二种方式增强迭代器 map.keySet()======");
     Iterator iterator = keySet.iterator();
     while (iterator.hasNext()) {
         Object key =  iterator.next();
         System.out.println(key + "=" + map.get(key));
     }

     //第二种   values

     Collection values = map.values();
     System.out.println("======第一种方式增强for map.values()======");
     for (Object value :values) {
         System.out.println(value);
     }

     System.out.println("======第二种方式增强迭代器 map.values()======");
     Iterator iterator1 = values.iterator();
     while (iterator1.hasNext()) {
         Object value = iterator1.next();
         System.out.println(value);
     }

     //第三种   EntrySet
     Set entrySet = map.entrySet(); //EntrySet<entry<k,v>>

     System.out.println("======第一种方式增强for entrySet======");
     for (Object entry :entrySet) {
         Map.Entry m = (Map.Entry) entry;
         System.out.println(m.getKey() + " = " + m.getValue());
     }

     System.out.println("======第二种方式增强迭代器 entrySet======");
     Iterator iterator2 = entrySet.iterator();
     while (iterator2.hasNext()) {
         Object entry = iterator2.next();
         Map.Entry m = (Map.Entry) entry;
         System.out.println(m.getKey() + " = " + m.getValue());
     }

 }
}

HashMap

HashMap底层机制
  1. HashMap底层维护了Node类型的数组table,默认为null

  2. 当创建对象时,将加载因子(loadfactor)初始化为0.75.

  3. 当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的key相是否等,如果相等,则直接替换val;如果不相等,需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。

  4. 第1次添加,则需要扩容table容量为16,临界值(threshold)为12 (16*0.75)

  5. 以后再扩容,则需要扩容table容量为原来的2倍(32),临界值为原来的2倍,即24,依次类推.

  6. 在Java8中,如果-条链表的元素个数超过 TREEIFY THRESHOLD(默认是8),并且table的大小>= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树).

  7. HashMap是Map接口使用频率最高的实现类。

  8. 如果添加相同的key ,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)

  9. 与HashSet-样,不保证映射的顺序,因为底层是以hash表的方式来存储的.

  10. HashMap没有实现同步,因此是线程不安全的

HashTable

HashTable 基本介绍。
  1. 存放的元素是键值对:即K-V
  2. hashtable的键和值都不能为null
  3. hashTable使用方法基本上和HashMap-样
  4. hashTable是线程安全的,hashMap 是线程不安全
  5. 底层有数组 HashtabLe E n t r y [ ] ( H a s h t a b L e Entry[ ] (HashtabLe Entry[](HashtabLeEntry 类似 HashtabLe$Node) 初始化大小为11
  6. 临界值threshold 8 = 11 * 0.75
  7. 扩容:按照自己的扩容机制来进行即可.
HashMap 与 HashTable 对比
版本线程安全(同步synchronized)效率允许null键null值
HashMap1.2不安全允许
HashTable1.0安全较低不允许

Properties

Properties 介绍
  1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。

  2. 他的使用特点和 HashTable 类似

  3. Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改

  4. 说明:工作后xx.properties 文件通常作为配置文件。

  5. public class Properties02 {
     public static void main(String[] args) throws IOException {
         Properties properties = new Properties();
         //我在这边的根目录读取不到,只能用绝对路径
         properties.load(new FileReader("C:\\Users\\86152\\IdeaProjects\\kuangshen-study\\baseLearn\\src\\mysql.properties"));
         //把 K-V 显示在控制台
         properties.list(System.out);
         String user = properties.getProperty("user");
         String pwd = properties.getProperty("pwd");
         System.out.println("user=" + user);
         System.out.println("pwd=" + pwd);
     }
    }
    
    public class Properties03 {
     public static void main(String[] args) throws IOException {
         Properties properties = new Properties();
         properties.setProperty("charset","utf8");
         properties.setProperty("user","汤姆");
         properties.setProperty("pwd","abc111");
         properties.store(new FileOutputStream("C:\\Users\\86152\\IdeaProjects\\kuangshen-study\\baseLearn\\src\\mysql2.properties"),null);
    //        properties.store(new FileOutputStream("/mysql.properties"),null);
         System.out.println("配置文件保存成功");
     }
    }
    

总结

开发中如何选择集合实现类

  1. 先判断存储的类型(一组对象[单列]或-组键值对[双列])
  2. 一组对象[单列]: Collection接口
    • 允许重复: List
      • 增删多: LinkedList [底层维护了一个双向链表,链表易增删]
      • 改查多:ArrayList [底层维护Object类型的可变数组,下标易定位]
    • 不允许重复: Set
      • 无序: HashSet [底层是HashMap,维护了个哈希表 即(数组+链表+红黑树)]
      • 排序: TreeSet
      • 插入和取出顺序一致: LinkedHashSet , 维护数组+双向链表
  3. 一组键值对[双列]: Map
    • 键无序: HashMap [底层是:哈希表jdk7: 数组+链表,jdk8:数组+链表+红黑树]
    • 键排序: TreeMap
    • 键插入和取出顺序一致: LinkedHashMap
    • 读取文件Properties
TreeSet 简述
  1. 底层是TreeMap
  2. 当我们使用无参构造器,创建TreeSet时, 仍然是无序的
  3. 使用TreeSet提供的一个构造器,可以传入一个比较器(匿名内部类)并指定排序规则
//可以直接debug看源码
@SuppressWarnings({"all"})
public class TreeSet_ {
 public static void main(String[] args) {
//        TreeSet treeSet = new TreeSet();
     TreeSet treeSet = new TreeSet(new Comparator() {
         @Override
         public int compare(Object o1, Object o2) {
//                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");

     System.out.println(treeSet);
 }
}
TreeMap 简述
  1. 构造器。把传入的实现了Comparator接 口的匿名内部类(对象),传给给TreeMap的comparator
  2. 调用put方法
    • 第一次添加,把k-v 封装到Entry对象,放入root
    • 调用compare
//可以直接debug看源码
@SuppressWarnings({"all"})
public class TreeMap_ {
 public static void main(String[] args) {
     TreeMap treeMap = new TreeMap(new Comparator() {//比较器排序
         @Override
         public int compare(Object o1, Object o2) {
             return ((String)o1).compareTo((String) o2);
//                return ((String)o1).length() - ((String)o2).length();
         }
     });
//        TreeMap treeMap = new TreeMap();

     treeMap.put("jack","杰克");
     treeMap.put("Tom","汤姆");
     treeMap.put("kristina","克斯替诺");
     treeMap.put("smith","史密斯");

     System.out.println(treeMap);
 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值