Java集合

集合

2021-06-06

Java集合框架概述

  1. 集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
    说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt, .jpg,.avi,数据库)
  2. 数组在存储多个数据方面的特点:
  • 一旦初始化以后,其长度就确定了。
  • 数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。比如: String[] arr;
    int[ ] arr; 0bject[] arr;
  1. 数组在存储多个数据方面的缺点:
  • 一旦初始化以后,其长度就不可修改。
  • 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
  • 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
  • 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
  1. 集合框架
|----Collection
        |----List接口:存储有序的、可重复的数据。 -->动态的数组
            |----ArrayList、LinkedList、Vector    
        |----Set接口:存储无序的、不可重复的数据。 -->高中学过的“集合”
            |----HashSet、LikedHashSet、TreeSet
|----Map:双列集合,用来存储一对数据(key -- value)。 -->高中学的函数 y = f(x)
            |----HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

Collection

  1. Collection接口中的方法(与生俱来的抽象方法)
//14个方法
Collection coll = new ArrayList();
//1.add(Objetct e)  :将元素e添加到集合coll中
coll.add("AA");
coll.add("BB");
coll.add(123);
coll.add(new Date());
//2.size()  :获取集合中的元素个数  
System.out.println(coll.size());
//3.addAll(Collection coll1) :将coll1集合中的元素添加到当前集合中
Collection coll1 = new ArrayList();
coll.addAll(coll1);
//4.clear()  清空集合元素
coll.clear();
//5.isEmpty()  :判断当前集合是否为空 (return size == 0;)
System.out.println(coll.size());
System.out.println(coll.isEmpty());
//6.contains(Object obj) :判断当前集合中是否包含obj
//在判断时会调用obj所在类的equals(),按顺序依次和集合中的每个元素进行比较
//所以:向Collection接口的实现类的对象中添加数据obj时,要求obj所在的类重写equals()方法
boolean contains = coll.contains(new Person(Jerry,20));
//7.containsAll(Collection coll1) :判断coll1中的元素是否都存在于本集合中
//8.bollean remove(Object obj) :移除本集合中的obj元素,并返回是否移除成功
//9.bollean removeAll(Collection coll1) :移除本集合中的包含在coll1中的所有元素(移除交集),并返回是否移除成功
//10.retainAll(Collection coll1) 求交集
//11.equals(Object obj) :obj是集合  比较两个集合是否相同,ArraysList是有序的,顺序不一致则为false
//12.hashCode() :返回哈希值
//13.集合-->数组 toArray()
Object[] arr = coll.toArray();
//数组-->集合? 
List<String> list = Arrays.asList(new String[]{"AA","BB","CC"});
List list1 = Arrays.asList(new int[]{123,456});
List list2 = Arrays.asList(new Integer[]{123,456});
//14.iterator() :返回Iterator接口的实例,用于遍历集合元素,后面再讲

Iterator 迭代器接口

  • Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象
  • Iterator称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素
  • GOF给迭代器模式的定义为:提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式就是为容器而生。
  • Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力,如果需要创建Iterator对象则必须有一个被迭代的集合
  • 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前
hasNext();
next();

Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
Iterator iterator = coll.iterator();
while(iterator.hasNext()){//hasNext判断是否还有下一个元素
    System.out.println(iterator.next());//next() ①指针下移 ②将下移以后集合位置上的元素返回
}



remove();//可以在遍历的时候删除集合中的元素,不同于集合直接调用remove()
//注意:!如果还未调用next()或在上一次调用next方法之后已经调用了remove方法再调用remove都会报IllegalStateException    

Iterator iterator = coll.iterator();
while(iterator.hasNext()){//hasNext判断是否还有下一个元素
    Object obj = iterator.next();
    if("TOM".equals(obj)){
        iterator.remove();
    }
}
iterator = coll.iterator();
while(iterator.hasNext()){
    System.out.println(iterator.next());

  • foreach
  • JDK5.0提供了另一种遍历集合的方式:foreach循环迭代访问Collection和数组
  • 这种遍历方式不需要获取Collection或数组的长度,无需使用索引访问元素
  • 遍历集合的底层其实也是使用Iterater迭代器
//for(集合元素的类型 局部变量 : 集合对象)

for(Object obj : coll){
    System.out.println(obj);
}

//for(数组元素的类型 局部变量 : 数组对象)
int[] arr = new int[]{1,2,3};

for(int i : arr){
    System.out.println(i);
}

练习题:
@Test
public void test(){
    String arr = new String[]{"MM","MM","MM"};
    方式一:
    for(int i = 0; i < arr.length; i ++){
        arr[i] = "GG";
    }
    方式二:
    for(Sting s : arr){
        s = "GG";       
    }

    for(int i = 0; i < arr.length; i ++){
        System.out.println(arr[i]);
    }
    //方式一打印GG,方式二打印MM
}

Collection子接口之一—List

  • 鉴于JAVA中用数组来存储数据的局限性,我们通常用List替代数组
  • List集合中元素有序且可重复,集合中的每个元素都有其对应的顺序索引
  • List容器中的元素都对应一个int型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
   |----ArrayList:List接口的主要实现类  jdk1.2 线程不安全 效率高,底层使用Object[] elementData存储
   |----LinkedList:                    jdk1.2 底层使用双向链表存储,对于频繁的插入和删除操作,使用此类效率比ArrayList高                        
   |----Vector   :List接口的古老实现类  jdk1.0 线程安全 效率低,底层使用Object[] elementData存储 
   
  • ArrayList底层源码分析
//jdk7
ArrayLisy list = new ArrayList();//底层创建了长度是10的Object[] elementData数组
list.add(123);//elementData[0] = new Integer(123);
...
list.add(321);//如果此次添加导致底层elementaData数组容量不够,则扩容。
//默认情况下扩容为原来的1.5倍,然后将原来数组中的数据复制到新的数组中
//结论:建议开发中使用带参的构造器
ArrayList list = new ArrayList(int capacity);


//jdk8作了一些变化
ArrayList list = new ArrayList();//底层Object[] elementData初始化为{},并没有创建长度是10的数组
list.add(123);//第一次调用add时,底层才创建了长度为10的数组,并将123添加到elementData
//后面的添加和扩容操作与jdk7一样


//总结:jdk7中ArrayList的创建类似于单例的饿汉式  jdk8中类似于单例的懒汉式
//jdk8这种方式延迟了数组的创建,节省内存
  • LinkedList底层源码分析
LinkedList list = New LinkedList();//内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象

private static class Node(E){
    E item;
    Node(E) next;
    Node(E) prev;
    
    Node(Node<E> prev , E element ,Node<E> next){
        
        this.item element;
        this.next = next;
        this.prev = prev;
        
    }
}
  • Vector底层源码分析
  • jdk7和jdk8中通过Vector()构造器创建对象时,底层都是创建了长度为10的数组,在扩容时,默认扩容为原来数组长度的2倍。
  • 虽然它是线程安全的,但是在多线程问题中也基本不用它了,Collections工具类中有方法可以让ArrayList变成线程安全的~!
List接口中常用方法
  • List除了从Collection集合继承的方法外,List集合里添加了一些根据索引来操作集合元素的方法
@Test
public void test(){
    ArrayList list = new ArrayList();
    lsit.add(123);
    lsit.add(456);
    lsit.add("AA");
    lsit.add(new Person(Tom,24));
    lsit.add(456);
    
    /*1. void add(int index, Object ele):在index位置插入ele元素*/
    list.add(2,"BB");
    
    /*2. boolean add(int index, Collection eles):在index位置插入集合Collection*/
    List list1 = Arrays.asList(1,2,3);
    list.addAll(2,list1);
    System.out.println(list.size());//9
    
    /*3. Object get(int index); 获取指定索引位置的元素*/
    System.out.println(get(0));
    
    /*4. int indexOf(Object obj); 返回obj在集合中首次出现的位置 */
    System.out.println(list.indexOf("AA"));//2
    System.out.println(list.indexOf("CC"));//-1 没有就返回-1    
    
    /*5. int lastIndexOf(Object obj); 返回obj在集合中最后一次出现的位置 */
    System.out.println(list.indexOf(456));//4
    System.out.println(list.indexOf(789));//-1 没有就返回-1     
    
    /*6.Object remove(int index); 删除指定索引处的元素,并返回该元素*/
    System.out.println(list.remove(0));//123
    
    /*7. Object set(int index,Object ele); 设置指定索引处的元素为ele */
    System.out.println(list.set(1,"CC")); //[456,"CC","TOM,24",456] 
    
    /*8. List subList(int fromIndex , int toIndex);  返回从fromIndex到toIndex位置的左闭右开区间的子集合*/
    List subList = list.subList(2,4);
    System.out.println(subList);//["AA","Tom,24"]
    
}
  • 总共15+8=23个方法!总结一下常用方法
增:add(Object obj)
删:Object remove(int index) / boolean remove(Object obj)
改:set(int index,Object ele)
查:get(int index)
插:add(int index, Objecrt ele)
长度:size()
遍历:①Iterator ②增强for ③普通的循环也可以
  • List的遍历
@Test//遍历
public void test(){
    ArrayList list = new ArrayList();
    lsit.add(123);
    lsit.add(456);
    lsit.add("AA");
    //方式一:迭代器
    Iterator iterator = list.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }
    //方式二:增强for
    for(Object obj : list){
        System.out.println(obj);
    }
    //方式三:普通for
    for(int i = 0 ; i < list.size() ; i ++){
        System.out.println(list.get(i));
    }    
    
}    
    

Collection接口的子接口之二----Set接口

  • Set是Collection接口的子接口,它没有提供额外的方法
  • Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败
  • Set判断两个对象是否相同不是用 == 而是用 equals()
|----Collection
        |----Set接口:存储无序的、不可重复的数据。 -->高中学过的“集合”
            |----HashSet:
                - HashSet是Set接口的典型实现,大多数时候使用Set集合时都是使用这个实现类
                - HashSet按Hash算法来存储集合中的元素,因此具有很好的存取、查找、删除性能
                - HashSet具有以下特点:
                    - 不能保证元素的排列顺序
                    - HashSet不是线程安全的
                    - 集合元素可以是null
                - HashSet集合判断两个元素是否相等的标准:
                    两个对象通过hashCode()方法比较相等并且两个对象的equals()返回值也相等
            |----LikedHashSet:
                - LinkedHashSet它其实是HashSet的一个子类
                - 底层存储结构和HashSet一致
                - 添加元素的时候,还按添加顺序形成一个双向链表
                - 遍历的时候,可以按照添加的顺序遍历 
                - 对于频繁的遍历操作,LinkedHashSet效率更高一些
            |----TreeSet:
                - 底层结构是二叉树(红黑树)
                - 向treeSet中添加的元素,必须是相同类的对象
                - 可以按照添加对象的指定属性进行排序(Comparable、Comparator)
  • Set的无序性和不可重复性怎么理解?
以HashSet的无序性和不可重复性
1. 无序性 ≠  随机性,添加元素不是按顺序存进底层数组中的,所以遍历的出来的顺序不是添加时的顺序。
元素在数组中的存储位置是哈希值决定的,由Hashcode()方法计算出哈希值
2.不可重复性:保证添加的元素按照equals()判断时,不能返回true,即相同的元素只能添加一个

HashSet添加元素的过程:
向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,根据此哈希值,通过
某种算法计算出元素a在HashSet底层数组中的存放位置(索引位置),判断此位置上是否有元素,如果没有元素则
将a放在此位置,如果此位置上有其他元素b,则比较a与b的哈希值,如果哈希值不相同,则a添加成功(注);
如果哈希值相同,则通过a.equals(b)来进行比较,如果equals方法返回true,则添加失败,如果equals方法
返回false,则a添加成功(注)。

注:元素a与b以链表的方式存储
jdk7:元素a放到数组中,指向原来的元素
jdk8:原来的元素放在数组中,指向元素a
七上八下
  • hashCode()和equals()的重写
对于存储在Set容器中的对象,一定要重写equals()和hashCode(Object obj)要求相等的对象必须有相等的散列码  
  • TreeSet的使用
@Test
public void test(){
    TreeSet set = new TreeSet;
    set.add(123);
    set.add("AA");//报错了,必须添加相同类的对象
}

@Test
public void test(){
    TreeSet set = new TreeSet();
    set.add(34);
    set.add(-34);
    set.add(43);
    set.add(11);
    set.add(8);    
    
    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());//按从小到大排的
    }
}
@Test
public void test(){

    TreeSet set = new TreeSet();
    set.add(new User(Tom,12));
    set.add(new User(Jerry,12));        //报错了!User类没有实现comparable接口(没有compareTo方法)
    set.add(new User(Mike,12));
    set.add(new User(Jone,12));
  
    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

//User类继承comparable接口,重写compareTo()方法
@Override
public int compareTo(Object o){
    if(o instanceof User){
        User user = (User)o;
        return this.name.compareTo(user.name);
    }else{
        throw new RuntimeException)("输入的类型不匹配");
    }
}
@Test
public void test(){

    TreeSet set = nee TreeSet();
    set.add(new User(Tom,12));
    set.add(new User(Jerry,12));        
    set.add(new User(Mike,12));
    set.add(new User(Jone,12));
    set.add(new User(Tom,56));      //这个Tom没遍历出来,TreeSet里如果compareTo返回值是0,那就认为是相同的元素
  
    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

//稍作修改
@Override
public int compareTo(Object o){
    if(o instanceof User){
        User user = (User)o;
        //return this.name.compareTo(user.name);
        int comepare = this.name.compareTo(user.name);
        if(compare != 0){
            return compare;
        }else{
            return Interger.compare(this.age,user.age);
        }
    }else{
        throw new RuntimeException)("输入的类型不匹配");
    }
}

- 上面是自然排序
- 下面用comparator

@Test
public void test(){
    
    Comparator com = new Comparator(){
        //按照年龄从小到大排序
        @Override
        public int compare(Object o1,Object o2){
            if(o1 instanceof User && o2 instanceof User){
                User u1 = (User)o1;
                User u2 = (User)o2;
                return Integer.compare(u1.getAge(),u2.getAge());
            }else{
                throw new RuntimeException("输入的数据类型不匹配");
            }
        }
    };
    
    TreeSet set = new TreeSet(com); //不带参数的构造器默认用自然排序
    set.add(new User(Tom,12));
    set.add(new User(Jerry,12));        
    set.add(new User(Mike,12));
    set.add(new User(Jone,12));
    set.add(new User(Tom,56));      
  
    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

自然排序中,比较两个对象是否相同的标准为: compareTo()返回0.不再是equals().
定制排序中,比较两个对象是否相同的标准为: compare()返回0.不再是equals().

  • 练习题:
练习一:
//在List内去除重复数字值,要求尽量简单
public List duplicateList(List list){
    HashSet set = new HashSet();
    set.addAll(list);
    return new ArrayList(set);
}
练习二:

@Test
public void test(){

    HashSet set = new HashSet();
    Person p1 = new Person(1001,"AA");
    Person p2 = new Person(1002,"BB");
    
    set.add(p1);
    set.add(p2);
    System.out.println(set); /*{(1001,"AA"),(1002,"BB")}*/
    
    p1.name = "CC";
    set.remove(p1);
    System.out.println(set);/*{(1001,"CC"),(1002,"BB")}*/
    
    set.add(new Person(1001,"CC"));
    System.out.println(set);/*{(1001,"CC"),(1002,"BB"),(1001,"CC")}*/

    set.add(new Person(1001,"AA"));/*{(1001,"CC"),(1001,"AA"),(1002,"BB"),(1001,"CC")}*/
    System.out.println(set);    
    
}

Map

|----Map:(JDK1.2)双列数据,存储key-value键值对----类似于高中学的函数y=f(x)
    |----HashMap:作为Map的主要实现类(JDK1.2),线程不安全的,效率高;可以存储null的key和value
        |----LinkedHashMap:(JDK1.4)在HashMap基础上加了一对指针,保证在遍历Map元素时,可以按照添加元素顺序进行遍历;对于频繁的遍历操作,它的效率比HashMap更高  
    |----TreeMap:(JDK1.2)可以按照添加的key-value进行排序,实现排序遍历(key的自然排序或者定制排序);底层使用红黑树
    |----Hashtable:作为Map的古老实现类(JDK1.0)类似于Vector,线程安全,效率低;不能存储null的key和value;即使是多线程的也不用它,而是使用Collections工具类将HashMap变为线程安全的
        |----Properties:常用来处理配置文件;key和value都是String类型    

public class MapTest{
    @Test
    public void test(){
        Map map = new HashMap();
        map.put(null,null);//ok
        map = new Hashtable();
        map.put(null,null);//Exception
    }
}        
        
HashMap的底层结构:JDK7之前:数组+链表       
                   JDK8:数组+链表+红黑树
                   
                   
面试题:1.HashMap的底层实现原理
        2.HashMap和Hashtable的异同
        3.CurrentHashMap和Hashtable的异同(暂时不讲)


  • Map结构的理解
Map中的key:无序的、不可重复的,使用Set存储所有的key  ---->key所在的类要重写hashcode()和equals()(HashMap为例;TreeMap不同)
Map中的value:无序的,可重复的,使用Collection存储所有的value ---->value所在的类要重写equals()
一个键值对 key--value 构成了一个Entry对象。Map中的entry是无序的不可重复的,使用Set存储所有的entry
  • HashMap的底层实现原理
JDK7
HashMap map = new HashMap();
在实例化以后,底层创建了长度是16的一维数组Entry[] table
map.put(key1,value1) (在此之前可能已经执行过多次put了)
首先调用key1所在类的hashCode()计算key1的哈希值,此哈希值经过某种算法计算之后,得到在Entry数组中存放的位置,
如果此位置上的数据为空,则key1-value1添加成功。----情况1
如果此位置上的数据不为空(意味着此位置上存在着一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
    如果key1的哈希值和已经存在的多个数据的哈希值都不相同,此时key1-value1添加成功----情况2
    如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较key1.equals(key2)
        如果equals()返回false:此时key1-value1添加成功----情况3
        如果equals()返回true:此时使用value1替换value2  
        
补充:1.关于情况2和情况3,此时key1-value1和原来的数据以链表的方式存储
      2.在不断地添加过程中会涉及到扩容问题,默认的扩容方式:扩容为原来容量的两倍,并将原有的数据复制过来
    
-------------------------------------------------------------------------------------------------------------------

JDK8相较于JDK7在底层实现方面的不同:
1.HashMap map = new HashMap();在实例化以后,底层没有创建长度是16的数组
2.JDK8底层数组不是Entry[] 而是Node[]
3.首次调用put()方法时,底层创建长度为16的数组
4.JDK7底层结构为 数组+链表,JDK8底层结构为 数组+链表+红黑树
    当数组某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组长度>64时
    此索引位置上的所有数据改为使用红黑树存储。

  • HashMap底层源码分析
面试题:
谈谈你对HashMap中put/get方法的认识,如果了解再谈谈HashMap的扩容机制,默认大小是多少?什么是负载因子(或填充比)?什么是吞吐临界值(或阈值、threshold)?

HashMap中的重要常量和变量
DEFAULT_INITIAL_CAPACITY: HashMap的默认容量:16
MAXIMUM_CAPACITY: HashMap支持的最大容量:2^30
DEFAULT_LOAD_FACTOR: HashMap的默认加载因子
TREEIFY_THRESHOLD: Bucket中链表长度大于该默认值,转化为红黑树
UNTREEIFY_THRESHOLD: Bucket中红黑树存储的Node小于该默认值,转化为链表
MIN_TREEIF_CAPACITY: 桶中的Node被树化时,最小的hash表容量。(当桶中的Node的数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行resize扩容操作,这个MIN_TREEIF_CAPACITY的值至少是TREEIFY_THRESHOLD的4倍)

table:存储元素的数组,总是2的n次幂
entrySet:存储具体元素的集
size:HshMap中存储的键值对的数量
modCount:HashMap扩容和结构改变的次数
threshold: 扩容的临界值 = 容量 * 填充因子
loadFactor: 填充因子
  • HashMap常用方法的使用
/*添加、删除、修改
Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中所有的key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
*/
puublic class MapTest{
    @Test
    public void test(){
        //put()
        Map map = new HashMap();
        map.put("AA",123); //添加
        map.put("BB",321);
        map.put("CC",456);
        map.put("AA",654); //修改
        
        System.out.println(map);//{AA=654,CC=456,BB=321}
        
        Map map1 = new HashMap();
        map.put("DD",321);
        map.put("EE",321);
        
        //putAll()
        map.putAll(map1);
        System.out.println(map);//{AA=654,CC=456,DD=321,EE=321,BB=321}
        
        //remove()
        Object value = map.remove("CC");
        System.out.println(map);
        System.out.println(value);
        
        //clear()
        map.clear();
        System.out.println(map.size());
        
        
        
    }
}

/*查询
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):判断是否包含指定的key
boolean containsValue(Object value):判断是否包含指定的value
int size();返回map中key-value对的个数
boolean isEmpty();判断当前map是否为空
boolean equals(Object obj);判断当前map和参数对象obj是否相等
*/
/*元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
*/
Set keyset = map.keySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
    Systemm.out.println(iterator.next());
}

Collection values = map.values();
for(Object obj : values){
    System.out.println(obj);
}
//遍历所有的key-value
//方式一:
Set entrySet = map.entrySet();
Iterator iterator1 = entrySet.iterator();
while(iterator1.hasNext()){
    Object obj = iterator1.next();
    Map.entry entry = (Map.entry)obj;
    System.out.println(entry.getKey() + "--->" + entry.getValue());//getKey()和getValue是Map的内部接口Entry的抽象方法
}
//方式二:
Set set = map.keySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
    Object key = iterator.next();
    Object value = map.getKey(key);
    Systemm.out.println(key + "=====" + value);
}
  • 总结
添加:put(Object key,Object value)
删除:remove(Object key)
修改:put(Object key,Object value)
查询:get(Object key)
长度: size()
遍历:keySet() / values() /entrySet()
  • TreeMap
  • 向TreeMap中添加key-value,要求key必须是同一个类的对象,因为要按照key进行排序:自然排序、定制排序
    //自然排序
    @Test
    public void test(){
        TreeMap map = new TreeMap();
        
        User u1 = new User("Tom",23);
        User u2 = new User("Jerry",24);
        User u3 = new User("Jack",20);
        User u4 = new User("Rose",18);
        
        map.put(u1,98);
        map.put(u2,88);
        map.put(u3,78);
        map.put(u4,100);
        
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while(iterator1.hasNext()){
        Object obj = iterator1.next();
        Map.entry entry = (Map.entry)obj;
        System.out.println(entry.getKey() + "--->" + entry.getValue());
    }
     
    //定制排序
    @Test
    public void test(){
        TreeMap map = new TreeMap(new Comparator(){
            @Override
            public int compare(Object o1,Object o2){
                if(o1 instanceof User && o2 instanceof User){
                    User u1 = (User)o1;
                    User u2 = (User)o2;
                    return Integer.compare(u1.getAge(),u2.getAge());
                }
                throw new RunTimeException("输入的类型不匹配!");
            }
        });
        
        User u1 = new User("Tom",23);
        User u2 = new User("Jerry",24);
        User u3 = new User("Jack",20);
        User u4 = new User("Rose",18);
        
        map.put(u1,98);
        map.put(u2,88);
        map.put(u3,78);
        map.put(u4,100);
        
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while(iterator1.hasNext()){
        Object obj = iterator1.next();
        Map.entry entry = (Map.entry)obj;
        System.out.println(entry.getKey() + "--->" + entry.getValue());
    }
}
  • HashTable不用了,关心的是它的子类Properties
  • Properties用来处理配置文件,key和value都是String类型

Collections工具类

  • Collections是一个操作Set、List和Map的工具类
  • Collections中提供了一些静态方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变,对集合对象实现同步控制等方法
  • 排序操作:
reverse(List):反转List中元素的顺序
shuffle(List):List集合元素进行随机排序
sort(List):根据元素的自然顺序对List集合元素按升序排序
sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
swap(List,int,int):List集合中i处元素和j处元素进行交换

Object max(Collection):根据元素的自然排序,返回给定集合中的最大元素
Object min(Collection):根据元素的自然排序,返回给定集合中的最小元素
Object max(CollectionComparator):根据Comparator指定的顺序,返回给定集合中的最大元素
Object min(CollectionComparator):根据Comparator指定的顺序,返回给定集合中的最小元素
int frequency(Collection,Object):返回指定集合中指定元素出现的次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll:(List list,Object oldVal,Object newVal)

@Test 
public void test(){
    List list = new ArrayList();
    list.add(123);
    list.add(43);
    list.add(3);
    list.add(-99);
    list.add(100);
    
    //List dest = new ArrayList();
    //Collections.copy(dest,list);//Source does not fit in dest
    
    List dest = Arrays.asList(new Object[list.size()]);
    System.out.println(dest.size());
    Collections.copy(dest,list);
    System.out.println(dest);
}

Collections类中还提供了多个synchronizedXxx()方法
这些方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值