java集合

  • Post author:
  • Post category:java



目录


集合


1.集合概述


1.1 什么是集合


1.2 集合


1.3 数据结构


1.4 集合所在的包


1.5 集合的继承结构图


1.6 集合两大类


总结(所有实现类)


2.Collection接口


2.1Collection常用方法


2.2迭代器(重点)


3.List接口


3.1List接口常用方法


3.2ArrayList集合


3.3链表:


3.4LinkedList集合


3.3.5Vector集合


4.泛型


5.Set接口


6.Map接口


6-1HashMap集合


6-2Hashtable集合


6-3Properties集合


6-4TreeMap集合


7.集合工具类


集合

1.集合概述

1.1 什么是集合

什么是集合?有什么用?

集合实际上就是一个容器可以来容纳其他类型的数据,集合可以放不同类型的元素

集合容量是无限的可以自动扩容。

集合为什么在开发中使用较多?
​
集合是一个容器,是一个载体,可以一次容纳多个对象,在实际开发中,假设连接数据库,数据库当中有十条记录,那么假设把这10条记录查询出来,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将一个数据,一个数据展现出来。


理解为运输数据的

1.2 集合

集合不能直接存储基本数据类型,另外集合也不能最直接存储java对象,集合当中存储的都是java对象的内存地址(或者说集合中存储的是引用)

注意:

集合在java中本身是一个容器,是一个对象。

集合中任何时候存储的都是引用

1.3 数据结构

在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中储存元素等于将数据放到了不同的数据结构中。

什么是数据结构?

数据存储的结构就是数据结构,不同的数据结构储存方式不同。

例如: 数组 二叉树 链表 哈希表 以上这些都是常见的数据结构

java中已经将数据结构实现了,已经写好了这些常用的集合类,只需要掌握怎么用、在什么情况下选择哪一种合适的集合去使用即可。

1.4 集合所在的包

集合在java JDK中的哪个包下?


所有的集合类和集合接口,都在在

java.util.*

包下。

new ArrayList();创建一个集合,底层是数组。
new LinkedList();创建一个集合对象,底层是链表。
new TreeSet();创建一个集合对象,底层是二叉树。

1.5 集合的继承结构图


Map

1.6 集合两大类

在java中集合分为两大类:

  • 一类是单个方式存储元素:

单个方式存储元素,这一类集合中超级父接口:java.util.Collection;

  • 一类是以键值对(key value )的方式存储元素

以键值对的方式存储元素,这一类集合中超级父接口: java.util.Map;

总结(所有实现类)

ArrayList:底层是数组。
Linked:底层是双向列表。
Vector:底层是数组,线程安全的,效率较低,使用较少
HashSet:底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分了。
TreeSet:底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合key部分了。
HashMap:底层是哈希表。
Hashtable:底层也是哈希表,只不过线程安全的,效率较低,使用较少。
Properties:是线程安全的,并且key和value只能存储字符串String
TreeMap:底层是二叉树。TreeMap集合的key可以自动按照大小顺序排序。
  • List集合存储元素的特点:

有序可重复

有序:存进去的顺序和取出的顺序相同,每一个元素都有下标。

可重复:存进去1,可以在存储一个1

  • Set(Map)集合存储元素的特点:

无序不可重复

无序:存进去的顺序和取出的顺序不一定相同,另外Set集合中元素没有下标。

不可重复:存进去1,不能再存1了。

  • SortedSet(SortedMap)集合存储元素的特点:

    首先是无序不可重复的,但是SortedSet集合中的元素是可排序的。

    无序:存进去的顺序和取出的顺序不一定相同,另外Set集合中元素没有下标。

    不可重复:存进去1,不能再存1了。

    可排序:可以按照大小顺序排列。

Map集合的key就是一个Set集合。

往Set集合中放数据,实际上放到了Map集合的key部分。

2.Collection接口

1.Collection中能存放什么元素?

  • 没有使用”泛型“之前,Collection中可以存储Object的所有子类

  • 使用了”泛型”之后,Collection中只能存放某个具体类型的子类

集合后期我们会学习“泛型”的语法(集合中不能直接存储基本数据类型,java对象,只是存储java对象的内存地址)

2.1Collection常用方法

boolean add(Object e) //像集合中添加元素
int size() ;//获取元素个数
void clear();//清空集合
boolean contains(Object o);//判断当前集合中是否包含元素o,包含返回true不包含返回false
boolean remove(Object o)//删除集合中某个元素
boolean isEmpty()//判断该集合中元素的个数是否为0    
Object[] toArray() //调用这个方法可以把集合转换成数组

package com.test01;
​
import java.util.ArrayList;
import java.util.Collection;
​
public class test01 {
    public static void main(String[] args) {
        System.out.println("helloworld");
        //接口是抽象的不能实例化,所以使用多态
        Collection  c =new ArrayList();
        
        //添加元素add()
        c.add("123");
        c.add(12345);//自动装箱(java5的新特性),实际上是放进去了一个对象的内存地址。Integer x = new Integrt(1200);
        c.add(789);//自动装箱
        c.add(new Student());
        c.add(true);
        //获取元素个数 size()
        System.out.println(c.size());//5
       
        //清空集合 clear()
        c.clear();
        System.out.println(c.size());//0
        c.add("c");
        c.add("l");
        c.add("j");
        
        //判断是否包含c contains()
        boolean flag1 = c.contains("c");
        boolean flag2 =c.contains("d");
        System.out.println("判断是否包含某个元素:contains()");
        System.out.println(flag1);//true
        System.out.println(flag2);//false
        System.out.println(c.size());
        
        //删除元素 remove()
        System.out.println("删除元素:remove()");
        c.remove("c");
        System.out.println(c.size());
​
        //判断集合是否为空isEmpty()、clear()
        System.out.println("判断元素是否为空:isEmpty()");
        System.out.println(c.isEmpty());
        c.clear();//清空集合
        System.out.println(c.isEmpty());//true
        
        //集合转换成数组 toArray()
        c.clear();
        c.add(123);
        c.add("hello");
        c.add("world");
        c.add("chen");
        
        //转换成数组
        Object[] o = c.toArray();
        for(int i=0;i<o.length;i++){
            System.out.println(o[i]);
        }
        //转换成数组
        Object[] objs = c.toArray();
        for(int i = 0; i<objs.length;i++){
            //遍历数组
            object o = objs[i];
            System.out.println(o);  toString方法在String和Integer中都重写了。
        }
    }
​
}
class Student{
​
}

2.2迭代器(重点)

迭代器(迭代集合:遍历集合中的元素) 继承的Iterable中的方法

package com.test01;
​
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
​
public class test02 {
    public static void main(String[] args) {
//以下迭代方式/遍历方式,是所有Collection通用的一种方式,
//在Map集合中不能用。在所有的Collection以及子类中使用。
        
        //创建集合对象 
        Collection c =new HashSet();
        c.add(123);
        c.add(456);
        c.add(789);
        c.add(new test());
​
        //第一步:获取集合对象的迭代器对象
        Iterator it=c.iterator();
        //第二步:通过获取的迭代器对象开始迭代
        
        /**
         *如果接下来还有对象可以迭代,hasNext就返回true,如果没有元素可以迭代了就返回false(数据结构中单链表的方式)
         * next:获取下一个元素
         */
        while(it.hasNext()){
            System.out.println(it.next());
//自动装箱:Integer等和String都重写了toString方法,而自定义的类没有重写所以输出的是地址
        }
    }
}
class test{
//没有重写toString方法
}

2.2.1图解

该画法不太精确,因为集合里面实际上存的是地址

hasNext方法: boolean hadNext = it.hasNext();
//这个方法返回false表示没有更多的元素可以迭代了。返回true,表示还有元素可以迭代
hasNext方法:
//这个方法让迭代器前进一位,并且将指向的元素返回(拿到)。  

2.2.2案例

package com.test01;
​
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
​
public class test03 {
    public static void main(String[] args) {
        //创建集合对象
        Collection ao =new ArrayList();
        //添加元素
        ao.add(123);
        ao.add(456);
        ao.add(789);
        ao.add(159);
        //创建迭代对象
        Iterator ii =ao.iterator();
        //
        while(ii.hasNext()){
            Object o = ii.next();//注:调用一次next就会使元素后移一个
            if(o instanceof Integer){
                System.out.println("Interger类型");//存进去什么类型,输出还是什么类型
            }
            System.out.println(o);//只不过会在输出的时候变成字符串类型,因为这里println会调用toString方法
        }
​
        System.out.println("---------------------------------");
         //HashSat无序不重复
         //无序:存进去和取出的顺序不一定相同,不可重复
        Collection cc =new HashSet();
          cc.add(1);
          cc.add(2);
          cc.add(3);
          cc.add(6);
          cc.add(8);
          cc.add(1);
          cc.add(1);
          cc.add(1);
          cc.add(1);
​
        Iterator iii= cc.iterator();
          while(iii.hasNext()){
              System.out.println(iii.next());
          }
    }
}

2.2.3contions()方法

判断集合中是否包含某个对象o 如果包含返回true,不包含返回false

底层是调用了equals()方法

package com.Swing;

import java.util.ArrayList;
import java.util.Collection;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/15:52
 * @Description:
 */
public class ContionsTest {
    public static void main(String[] args) {
        Collection t= new ArrayList();
        String s1 = new String("123"); //0x1111
        t.add(s1);//放进去了一个"123"
        String s2 = new String("456");//0x2222
        t.add(s2);
        //输出个数
        System.out.println(t.size());

        String s3 = new String("123");//0x5555
        System.out.println(s3.equals(s1));//字符串的比较会调用equals方法。
        System.out.println(t.contains(s3));//true ,判断集合中是否含有"abc"
        //t集合中包含s3
    }
}

contains方法是用来判断集合中是否包含某个元素的方法,他在底层调用了equals方法进行比对(String的equals方法比较的是内容),所以equals方法返回true就表示包含了这个元素。

Object方法的equals方法用双等号,比较的是内存地址。类中没有重写equals方法就调用的是Object里的equals方法。

  • 放在集合里面的元素要重写equals方法。

2.2.4remove()方法

remove方法底层也调用了equals方法

package com.Swing;

import java.util.ArrayList;
import java.util.Collection;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/16:37
 * @Description:
 */
public class RemoveTest {
    public static void main(String[] args) {
        Collection t = new ArrayList();

        Integer i1= new Integer(123);
        t.add(i1);
        System.out.println(t.size());//1
        Integer i2 = new Integer(123);
        System.out.println(t.remove(i2));//true
        System.out.println(t.size());//0
    }
}

2.2.5迭代器是快照

//迭代器就像是快照,只会迭代出快照里的元素,如果要修改元素那么就必须重新快照(即重新迭代)或者采用Iterator里面的remove方法来移除元素


当集合的结构发生改变时,迭代器必须重新获取


如果还是用以前老的迭代器,会出现异常:java.util.ConcurrentModifirionException

package com.Collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/17:06
 * @Description:
 */
public class Test01 {
    public static void main(String[] args) {
        Collection c= new ArrayList();
        c.add(123);
        c.add(456);
        c.add(789);

        Iterator i = c.iterator();
        while(i.hasNext()){
            Object o= i.next();
            c.remove(123);
            System.out.println(o);
        }

        /**
         *删除元素后,集合结构发生改变,应该重新获取迭代器对象。
         * Exception in thread "main" java.util.ConcurrentModificationException
         */
    }
}


总结:在迭代集合元素的过程中(迭代器对象创建完成后),不能调用集合对象的remove方法删除元素,及不能改变集合的结构

因为:直接通过集合去删除元素没有通知迭代器(导致迭代器的快照和原集合状态不同)


图解

直接使用集合删

使用迭代器删

底层会不断检查快照余真实结构的关系,如果发生了变化就会报错

解决方法:
    //使用迭代器来删
 Iterator i = c.iterator();
        while(i.hasNext()){
            Object o= i.next();
            i.remove();//删除的一定是迭代器当前返回的对象,获取之后就立马删掉
            System.out.println(o);//能打印出来是因为,集合保存的是地址,删掉的是地址,但是内容是保存到常量池当中的。
        }
        System.out.println(c.size());//0

Iterator对象和Collection对象的remove方法是不一样的。

Collection的删除:直接通过集合去删除元素,没有通知迭代器,导致迭代器的快照与结构不同。就会报错
Iterator的删除: 把快照删了的时会把集合中的元素删掉(自动更新),及同时发生改变。不会出现异常


集合状态发生变化时,重新获取迭代器

3.List接口

特点:有序可重复,有下标

有序:List集合中的元素有下标,从0开始,以1递增

可重复:存储一个1,还可以存储1

3.1List接口常用方法

boolean add(Object e) //像集合中添加元素,默认加在末尾
void add(int index, Object element)//在指定位置上加入元素(第一个参数是下标)  效率较低不常用
    
Object get(int index);//根据下标取元素,List集合特有的遍历方式
//下标从0开始

int indexOf(Objcect o)//获取指定对象第一次出现的索引(下标)
int lastIndexOf(object o)//获取指定对象最后一次出现的索引(下标)
    
Object remove(int index) //删除指定下标的元素
    
Object set(int index,Object element)//修改指定位置的元素
package com.Collection;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/17:44
 * @Description:
 */
public class List01 {
    public static void main(String[] args) {
        //创建List对象
        List list = new ArrayList<>();
        //添加元素
        list.add(0,0);
        list.add(1);
        list.add(2);
        list.add(3);
        //List添加的独特方式(不常用)
        list.add(4,1);
        //遍历
        for(int i = 0;i <list.size();i++){
            System.out.println(list.get(i));
        }
        //获取第一次出现的索引
        System.out.println(list.indexOf(1));//1
        //获取最后一次出现的索引
        System.out.println(list.lastIndexOf(1));//4
    }
}

3.2ArrayList集合

底层是数组

1.Arraylist初始化容量是10(jdk13 底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量是10)

2.Arraylist底层是Object[]数组

3.指定初始化容量:

List list1 =new Arraylist(20);

默认初始化容量:

List list2=new List();

数组的长度

4.ArrayList集合的扩容

原容量的1.5倍,ArrayList集合底层是数组,怎么优化?

尽可能少的扩容,因为数组扩容的效率比较低,建议在使用ArrayLIst集合的时候估计元素的个数给定一个初始化容量。

5.数组的优点:检索效率比较高。(每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,然后知道下标,通过数学表达式计算出元素的内存地址没所以检索效率最高)

6.数组的缺点:随即增删元素效率比较低,但像数组末尾添加元素效率很高

另外数组无法存储大数据量。

7.面试:这么多的集合中用哪一个 : ArrayList集合, 因为往数组末尾添加元素效率不受影响。另外检索,查找某个元素时比较多。

8.ArrayList集合是非线程安全的(不是线程安全的集合)

package com.Collection;
import java.util.ArrayList;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/17:58
 * @Description:
 */
public class ArrayListTest {
    public static void main(String[] args) {
        
        ArrayList arrayListTest = new ArrayList();
        System.out.println(arrayListTest.size());
        //可以指定容量
        ArrayList arrayListTest1 = new ArrayList(20);
        System.out.println(arrayListTest.size());
        //size()获取的是集合当前元素的个数,不是数组的容量。
    }
}
//二进制位运算
//100(二进制)  二转化成十: 00000100(4) 右移一位 00000010(2) [4/2]
//原先是4,现在增长2,增长之后是6,增长之后是增长之前的1.5倍(6是4的1.5倍)。

3.2.1ArrayList创建对象的三种方式

package com.Collection;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/18:29
 * @Description:命名三种方式
 */
public class ArrayListTest02 {
    public static void main(String[] args) {
        //第一种
        ArrayList arrayList1 = new ArrayList();
        //第二种,指定初始化容量
        ArrayList arrayList2 = new ArrayList(100);
        //第三种:HashSet转化成ArrayList
        HashSet hashSet= new HashSet();
        hashSet.add(123);
        hashSet.add(456);
        hashSet.add(789);
        hashSet.add(741);
        ArrayList arrayList3 = new ArrayList(hashSet);
        for(int i =0;i<hashSet.size();i++){
            System.out.println(arrayList3.get(i));
        }

    }
}

//将Arraylist转化为Hastset

package com.test01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

public class test05 {
    public static void main(String[] args) {
        
        /*Collection col =new ArrayList();
        String s1 =new String("123");

        col.add(s1);
        String s2 =new String("123");
        col.remove(s2);
        System.out.println(col.size());*/

        //创建Hashset集合
        Collection d =new HashSet();

        d.add(123);
        d.add(456);
        d.add(789);

        //指定初始化容量

        List f =new ArrayList(100);

        //通过这个方法可以将Hashset集合转换成List集合
       List  f1 =new ArrayList(d);

        for(int i=0;i<f1.size();i++){
            System.out.println(f1.get(i));
        }
    }
}

3.3链表:

两部分组成:一部分是数据 一部分是内存地址

3.3.1单项链表

3.3.2链表优缺点

链表优点:


随机增删元素的效率较高

(因为增删元素不会涉及到大量元素位移的问题)

由于链表上的元素在空间存储上内存地址不连续,所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高。在以后的开发中,如果遇到随机增删集合中元素的业务比较多时,建议使用LinkList。

链表缺点:


查询效率较低

(每一次查找某个元素的时候都需要从头节点开始往下遍历)

不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头结点开始遍历,知道找到位置。所以LinkedList集合检索查找的效率较低。

ArrayList:把检索发挥到极致(末尾检索效率还是很高的)

LinkListl:把随机增删发挥到极致

3.3.3双向链表

三部分组成:上一个对象内存地址,数据,下一个对象内存地址

p686LinkedList源码分析

初始化容量为null

3.4LinkedList集合

1.LinkedList集合底层采用了双向链表数据结构

2.LinkedList集合是双向链表,对于链表数据结构来说,随即增删效率较高检索效率较低。

3.链表中的元素在空间存储上内存地址不连续。

3.3.5Vector集合

1.底层也是一个数组

2.初始化容量是十

3.增么扩容的?

Vector扩容之后是原容量的2倍。10–>20—>40—>80

4.ArrayList扩容后是原容量的1.5倍。

5.Vector中所有的方法都是线程同步的,都带有synchtronized关键字,是线程安全的。(效率比较低,使用较少)

6.怎么将一个线程不安全的集合转换成线程安全的集合

使用集合工具类

java.util.Collections

java.util.Collection 借口

java.util.Collections 工具类

  List coll =new ArrayList();//非线程安全
       
        //变成线程安全
        Collections.synchronizedList(coll);

4.泛型

4.1式例

未使用泛型前

import org.w3c.dom.ls.LSOutput;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * 未使用泛型前
 */
public class test06 {
    public static void main(String[] args) {
        //准备猫对象、鸟对象
        Cat c= new Cat();
        Bird b =new Bird();

        // 不适用泛型,创建集合对象
        Collection cl= new ArrayList(20);
        
        //将对象添加到集合当中去
        cl.add(c);
        cl.add(b);
        
        //迭代器
        Iterator ie = cl.iterator();
        
        //迭代器获取元素
        while(ie.hasNext()){
           Object j = ie.next();//没使用泛型,得到的是Object对象

           if(j instanceof Animal){
           Animal animal =(Animal) j;
           animal.move();
               
           if(animal instanceof  Cat){
               Cat cc =(Cat)animal;
               cc.eat();
           }
           else if(animal instanceof Bird){
              Bird bb =(Bird)animal;
              bb.eat();
             }
           }

        }
    }
}
class Animal{
    public void move(){
        System.out.println("动物在移动!");
    }
}
class Cat extends Animal{
    public void eat(){
        System.out.println("毛在捕老鼠");
    }
}
class Bird extends Animal{
    public void eat(){
        System.out.println("鸟儿吃虫子!");
    }
}

使用泛型后

import org.w3c.dom.ls.LSOutput;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * 未使用泛型前
 */
public class test06 {
    public static void main(String[] args) {
        
        //指定collection集合只允许存储Animal类型的数据
        //用泛型来指定集合中存储的数据类型
        Collection<Animal> collection =new ArrayList<>();
         //创建猫、鸟对象
        Cat c1 =new Cat();
        Bird b1 =new Bird();
        //添加元素
        collection.add(c1);
        collection.add(b1);

        //使用泛型,这个迭代器迭代的类型是Animal,不能存储其他元素
        Iterator<Animal> iterator = collection.iterator();
          
        while(iterator.hasNext()){
            //直接通过迭代器获取了Animal类型
            Animal animal =iterator.next();//使用泛型直接得到Animal类型,不需要向下强制转型
            animal.move();
            if(animal instanceof  Cat){
                Cat cc =(Cat)animal;
                cc.eat();
            }
            else if(animal instanceof Bird){
                Bird bb =(Bird)animal;
                bb.eat();
            }
        }
    }
}
class Animal{
    public void move(){
        System.out.println("动物在移动!");
    }
}
class Cat extends Animal{
    public void eat(){
        System.out.println("毛在捕老鼠");
    }
}
class Bird extends Animal{
    public void eat(){
        System.out.println("鸟儿吃虫子!");
    }
}
  • 不使用泛型需要强制转换

  • 创建集合的时候需要指定泛型的类型,迭代的时候也需要指定泛型的类型。

1.JDK5.0之后推出的新特性

2.泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的(运行阶段泛型没用!)

3.泛型的优点:

第一:集合中存储的元素类型统一了。

第二:从集合中取出的元素类型是泛型指定的类型,不需要进行大量的”向下转型”!

4.泛型的缺点:

导致集合中存储的元素缺乏多样性

大多是业务中,集合中元素的类型还是统一的。所以这种泛型特性被大家认可。

4.2类型自动推断

JDK之后引入了:自动类型推断机制。(又称为钻石表达式)

自动类型推断机制(钻石表达式)JDK8之后
 Collection<Animal> collection =new ArrayList<Animal>();
 Collection<Animal> collection =new ArrayList<>();

4.3自定义泛型

自定义泛型的时候,<>尖括号中的是一个标识符,随便写。

java源码中经常出现:<E> \ <T>

E是Element首字母

T是Type的首字母

package com.test01;

import java.util.ArrayList;
import java.util.List;

public class test06 <E(标识符随便写)> {
    public static void main(String[] args) {

        Test<String> t =new Test();//指定是String类型

        t.dosome("123");//只能传String
        List<String> l =new ArrayList<>();
        

        Test<Integer> ti =new Test<>();
         ti.dosome(123);//只能传入Integer类型
    }
}
class Test<E>{
    Test () {}
    Test(E e){
        System.out.println("helloworld");
    }

    public void dosome(E e){
        System.out.println("做点什么");
    }
    public E dosome(E e){
        return e;
    }
}
package com.Collection;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/20:14
 * @Description:泛型测试
 */
public class GenericTest<随便写标识符> {
    static class DoSome<随便写标识符> {
        void DoSome(随便写标识符 o) {
            System.out.println(o.toString());
        }
    }
    public static void main(String[] args) {
        DoSome<String> doSome=new DoSome<>();
        doSome.DoSome("456");
    }
}

4.4增强for循环(foreach)


语法: for( 元素类型 变量名:数组或集合){System.out.println(元素变量名)}

package com.test01; 
/*
增强for
 */
public class test07 {
    public static void main(String[] args) {
        int[]arr={1,2,3,4,5,6};
        for(int i =0;i<arr.length;i++){
            System.out.println(arr[i]);
        }
        //增强for foreach
        /**
         * 语法:
         * for( 元素类型 变量名:数组或集合){System.out.println(变量名)}
         */
        System.out.println("==============================");
        for (int data:arr) {
            System.out.println(data);
        }
    }
}


三种输出方式

package com.test01;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class test08 {
    public static void main(String[] args) {
        List<String> l = new ArrayList<>();
        l.add("123");
        l.add("456");
        l.add("789");
        l.add("159");
        Iterator<String> i = l.iterator();
        while(i.hasNext()){
            System.out.println(i.next());
        }
        for(int a =0;a< l.size();a++){
            System.out.println(l.get(a));
        }
        for(String add:l){
            System.out.println(add);
        }
    }
}

5.Set接口

5.1HashSet集合

package com.test01;

import java.util.HashSet;
import java.util.Set;

public class test09 {
    public static void main(String[] args) {
        Set<String> e=new HashSet<>();
        e.add("123");
        e.add("789");
        e.add("123");
        e.add("123");
        e.add("1594");
        e.add("1594");

        for(String add:e){
            System.out.println(add);
        }
    }
}

特点:

1.存储时顺序和取出的顺序不同

2.不可重复

3.放到HashSet集合中的元素实际上是放到HashMap集合的key部分了。


初始化容量:16,初始化容量建议是2的倍数。扩容:扩容之后是原容量的2倍。

5.2TreeSet集合

特点:1.无序不可重复,但是存储的元素可以自动按照大小顺序排序!

1.TreeSet集合底层实际上是一个TreeMap

2.TreeMap集合底层是一个二叉树

3.放到Tree集合中的元素,等同于放到TreeMap集合Key部分了。

4.TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序


称为:可排序集合。升序!

package com.test01;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class test09 {
    public static void main(String[] args) {
      Set<String> s =new TreeSet<>();
      s.add("A");
      s.add("C");
      s.add("H");
      s.add("L");
      s.add("R");
      s.add("P");
      s.add("L");
        
      for(String ss:s){
          System.out.println(ss);
      }
    }
}
//结果  从小到大自动排序(按字典的排序方法排序)
A
C
H
L
P
R
package com.Collection;

import java.util.Set;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/14/9:29
 * @Description: TreeSet自动排序
 */
public class treeSetTest {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();

        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhaoliu");
        set.add("lisan");
        set.add("zhaosi");

        for(String ss :set){
            System.out.println(ss);
        }
        /**  按照字母大小一个一个比较
         * lisan
         * lisi
         * wangwu
         * zhangsan
         * zhaoliu
         * zhaosi
         */
    }
}

5.2.1自定义类型不能用TreeSet

原因: 没有实现

java.lang.Conparable

接口

package com.Collection;

import java.util.Set;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/10:56
 * @Description:
 */
public class TreeTest {
    public static void main(String[] args) {
        /**
         * Exception in thread "main" java.lang.ClassCastException:
         * class com.Collection.Customer cannot be cast to class java.lang.Comparable
         */
       Customer customer0= new Customer(12);
       Customer customer1= new Customer(12);
       Customer customer2= new Customer(12);
       Customer customer3= new Customer(12);
       Customer customer4= new Customer(12);

        Set<Customer> customers = new TreeSet<>();
        customers.add(customer0);
        customers.add(customer1);
        customers.add(customer2);
        customers.add(customer3);
        customers.add(customer4);

        for(Customer customer :customers){
            System.out.println(customer);
        }

    }
}

class Customer{
    public int age;

    public Customer(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
   
}

5.2.2实现比较

两种方法让自定义类型用TreeSet能实现比较

5.2.2.1重写compareTo

继承Comparable接口

package com.test02;

import java.util.Set;
import java.util.TreeSet;

/**
 * 书写比较规则 比较规则自己决定
 */
public class test002 {
    public static void main(String[] args) {
        users u0 =new users(123);
        users u1 =new users(456);
        users u2 =new users(789);

        Set<users> tree =new TreeSet<>();
        tree.add(u0);
        tree.add(u1);
        tree.add(u2);

        for(users set:tree){
            System.out.println(set);
        }

        /**
         * 结果:
         * users{age=123}
         * users{age=456}
         * users{age=789}
         */
    }
}

class users implements Comparable<users>{
    private int age;

    public users(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
     
    //重写compareTo方法
    //需要在这里编写比较的逻辑,按照什么进行比较!
    //k.compareTo(t.key)
    //拿着参数k和集合中的每一个k进行比较,返回值可能是>0 <0 =0  
    //比较规则是又程序员指定的,例如按照年龄升序或者年龄降序
    @Override
    public int compareTo(users o){ //c1.compare(c2)
        /**
         * this是c1
         * o就是c2
         * c1和c2比较就是this和o比较
         */
        /*int age1=this.age;
        int age2 =o.age;
        if(age1==age2){
            return 0;
        }else if(age1-age2<0){
            return -1;
        }else if(age1>age2){
            return 1;
        }*/

        return this.age-o.age;
    }
    //重写toString方法
    @Override
    public String toString() {
        return "users{" +
                "age=" + age +
                '}';
    }
}

案例

package com.Collection;

import java.util.Set;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/11:19
 * @Description:先按照年龄比,再按照名字排序
 */
public class TreeTests {
    public static void main(String[] args) {

        Set<Teacher> teachers = new TreeSet<>();

        teachers.add(new Teacher(12,"rdf"));
        teachers.add(new Teacher(18,"xdf"));
        teachers.add(new Teacher(14,"zdf"));
        teachers.add(new Teacher(22,"ydf"));
        teachers.add(new Teacher(22,"xdf"));

        for(Teacher teacher :teachers){
            System.out.println(teacher);
        }

    }
}
class Teacher implements Comparable<Teacher>{
    int age;
    String name;

    public Teacher(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public int compareTo(Teacher s) {

        if(s.age==this.age){
            return this.name.compareTo(s.name);//注意这里是this-s(二叉树的特点)
        }else{
            return this.age-s.age;//用当前元素去减之间已经放好的元素,中序遍历:左根右,左小右大
        }
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

5.2.2.2实现Comparator接口

单独编写一个比较器

比较器实现java.utli.Comparator接口

Comparable是Java.lang包下的

Comparator是java.util包下的

案例

package com.Collection;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/15:00
 * @Description:让Animals自定义类型可以进行比较
 */
public class TreeSetTest001 {
    public static void main(String[] args) {
        //创建Set集合的时候,需要使用这个比较器
        //Set<Animals> aniamls = new TreeSet<>();这样不行没有传入比较器

        //给构造方法传一个比较器
        Set<Animals> animals = new TreeSet<>(new AnimalComparator());

        //匿名内部类的方式
        Set<Animals> animal1 = new TreeSet<>(new Comparator<Animals>() {
            @Override
            public int compare(Animals o1, Animals o2) {
                return o1.age-o2.age;
            }
        });
        animals.add(new Animals(123));
        animals.add(new Animals(14));
        animals.add(new Animals(13));

        for(Animals Animal :animals){
            System.out.println(Animal);
        }

    }
}
class Animals{
    int age;

    public Animals(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Animals{" +
                "age=" + age +
                '}';
    }
}
//单独在这里编写一个比较器
//比较器实现java.util.Comparator接口。
//Comparable是java.lang包下的。(Comparator是java,util包下的)
class AnimalComparator implements Comparator<Animals> {
    @Override
    public int compare(Animals o1, Animals o2) {
        //指定比较规则
        //按照年龄排序
        return o1.age-o2.age;
    }
}

5.2.2.3如何选择

当比较规则不会发生改变的时候,或者说当比较规则只有一个的时候,建议实现Comparable接口。

如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Compararoe接口。

  • comparator接口的设计符合OCP原则

6.Map接口

java.util.Map接口中的常用方法


键值对:

Map<Integer,Students> map =new HashMap();

1.Map和Collection没有继承关系。

2.Map集合以key和value的方式存储数据类型:键值对

key和value都是引用数据类型。

key和value都是存储对象的内存地址。

key起到主导的地位,value是key的一个附属品。

3.常用方法:

Set keySet():获取Map集合的所有的key(所有的key是一个set集合)
get(Object key) :通过key来获取value
Collection values():获取Map集合中所有的value,返回Collection
Map.Entry<K,V> 
    Map集合通过entrySet()方法转化成的这个Set集合,Set集合中的元素类型是Map.Entry<K,V>
    Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是Map中的静态内部类。
    	<Map是个类名,Entry是Map的静态内部类>

package com.Collection;




import com.sun.jdi.Value;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/22:10
 * @Description:
 */
public class StaticTest {

    //静态内部类
    public static class MyClass{
        //静态内部类中的静态方法
        public static void InnerClass(){
            System.out.println("静态内部类的静态方法");
        }
        //静态内部类中的实例方法
        public void m2(){
            System.out.println("静态内部类的实例方法");
        }
    }

    public static void main(String[] args) {
        //Set集合中存储的对象是:MyClass.InnerClass类型
        Set<StaticTest.MyClass> set0 = new HashSet<>();

        //Set集合中存储的是字符串对象
        Set<String> set1 = new HashSet<>();

        Set<MyClass_plus.fun<Integer,String >> set2  =new HashSet<>();
    }
}

class MyClass_plus{
    public static class fun<k,v>{
    }
}

6.1静态内部类(补充)

package com.Collection;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/22:10
 * @Description:
 */
public class StaticTest {
    //声明一个静态内部类
    private  static class InnerClass{
        //静态方法
        public static  void m1() {
            System.out.println("静态内部类的静态方法执行!");
        }
        //实例方法
        public void m2(){
            System.out.println("静态内部类中的实例方法执行!");
        }
    }
    public static void main(String[] args) {
        //类名叫做:MyClass.InnerClass
        StaticTest.InnerClass.m1();

        //创建静态内部类对象
        StaticTest.InnerClass I1 =new StaticTest.InnerClass();
        I1.m2();
    }
}

6.2常用方法

Map接口常用的方法:

package com.Collection;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/13/22:58
 * @Description:获取values
 */
public class MapTest {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"chen");
        map.put(2,"liang");
        map.put(3,"jiang");
        //获取values
        Collection<String> collection=map.values();
        for(String str:collection){
            System.out.println(str);
        }
    }
}

6.3Map遍历(非常重要)

第一种遍历方式:

//第一种访问方式
package com.test01;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class test10 {
    public static void main(String[] args) {
        Map<Integer,String> m= new HashMap<>();
        m.put(1,"A");
        m.put(2,"B");
        m.put(3,"C");
        m.put(4,"D");
        m.put(5,"E");

        Set<Integer> set =m.keySet();
        Iterator<Integer> i =set.iterator();
        /**
         * 拿到key,通过key来获取value
         */
         while(i.hasNext()){
                Object o = i.next();
                //m.get(o)通过key访问value
             System.out.println(o+"="+m.get(o));
         }

         for(Integer keys: m.keySet()){
             System.out.println(keys+"="+m.get(keys));
        }
    }
}

第二种遍历方式:

package com.test01;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


public class test11 {
    public static void main(String[] args) {
        Map<Integer,String> s =new HashMap<>();
        s.put(0,"123");
        s.put(1,"456");
        s.put(2,"789");
        s.put(3,"753");
        s.put(4,"159");

        //通过调用 entrySet()把Map集合转化成Set集合
        Set<Map.Entry<Integer,String>> e =s.entrySet();
        //Set集合中元素的类型是Map.Entry

        //迭代器
        Iterator<Map.Entry<Integer,String>> iterator =e.iterator();

        while(iterator.hasNext())
        {
            Map.Entry<Integer,String> node =iterator.next();
            System.out.println(node.getKey()+"="+node.getValue());
        }
        System.out.println("===================================================");
        
        //使用for增强不需要用迭代器
        for(Map.Entry<Integer,String> nodes:e){
            System.out.println(nodes.getKey()+"="+nodes.getValue());
        }


    }
}

6-1HashMap集合

1.HashMap集合底层是哈希表(散列表)的数据结构

2.哈希表(散列表)是一个怎样的数据结构呢?

哈希表是一个数组和单项列表的结合体

数组:在查询方面效率很高,随机增删方面效率很低

单项列表:在随机增删方面效率较高,在查询方面效率较低

哈希表将以上的两种数据结构融合在一起,充分发挥他们各自的优点

3.HashMap集合底层的源代码

	Node[] nodes;
public class Node{
    Object k;
    Object v;
    Node next;
}

public Class HashMap{
    //HashMap底层实际上就是一个数组。(一维数组)
    Node<K,V>[]table;
    
    //静态的内部类HashMap.Node
    static class Node<K,V>{
        final int hash;//哈希值(哈希值的执行结果,hash值通过哈希函数/算法,可以转换称数组的下标。)
        final K key;//存储到Map集合中的key
        V value;//存储到Map集合中的value
        Node<K,V> next;//下一个节点的内存地址
    }
}
哈希表/散列表:一维数组,这个数组中每一个元素是一个单项链表。(数组和链表的结合体)

1.HashMap的put,get方法(必须掌握)


​​​​​​​

2.HashMap集合的key部分特点:


无序,不可重复。

为什么无序?因为不一定挂到那个单向链表上。

不可重复是怎么保证的?equals方法来保证HashMap集合的key不可重复。

如果key重复了,value会覆盖

  • 放在HashMap集合key部分的元素其实就是放到HashSet集合中了。所以HashMap集合中的元素也需要同时重写hashCode()+equals()方法。


同一个链表上的hash一定相同,因为他们的数组下标是一样的,但同一个链表上k和k的equals方法肯定返回的是false,都不相等

3.散列分布不均匀

4.重写hashset和equals方法

package com.Collection;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/14/0:35
 * @Description:
 */
public class MapTest02 {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap();
        map.put(1111,"1111");
        map.put(2222,"2222");
        map.put(3333,"3333");
        map.put(4444,"4444");
        map.put(4444,"4455");

        Set<Map.Entry<Integer,String>> set= map.entrySet();
        for(Map.Entry<Integer,String> node : set){
            System.out.println(node.getKey()+"="+node.getValue());//key重复value会被覆盖,且输出无序
        }
/**
 * 3333=3333
 * 1111=1111
 * 4444=4455
 * 2222=2222
 */
    }
}

放在HashSet集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法

  • HashMap集合的默认初始化容量是16,默认加载因子是0.75(默认加载因子是:当HashMap集合底层数组容量达到75%的时候,数组开始扩容。)

  • 重点:HashMap集合初始化容量必须是2的倍数,这也是官方推荐的

    这是因为达到散列均匀,为了提高HashMap集合的存储效率所必需的

5.equals的调用情况

向Map集合中存,以及Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法。

equals方法可能调用,也可能不调用

拿put(k,v)举例,什么时候equals不会调用?
k.hashCode()方法返回哈希值。
哈希值经过hash算法转换成数组的下标。
数组下标位置上如果是null,equals不需要执行。

拿get(k)举例,什么时候equals不会被调用?
k.hashCode()方法返回哈希值
哈希值经过哈希算法转换成数组的下标。
数组下标位置上如果是null,equals不需要执行。


总结:hashCode()返回的哈希值就是数组的下标


如果一个类的

equals方法

重写了,那么

hashCode()

方法必须重写。并且

equals方法

返回如果是

true



hashCode方法

返回的值必须一样。

package com.Collection;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/14/8:20
 * @Description:equals重写的时候hashCode方法也要重写。同时生成
 */
public class SetTest {
    public static void main(String[] args) {
        Student stu1 = new Student("张三");
        Student stu2 = new Student("张三");

        boolean bool=stu1.equals(stu2);
        System.out.println(bool);

        Map<Integer,Student> map = new HashMap<>();
        //特点,无序不可重复(内容不能重复)
        map.put(1,stu1);
        map.put(1,stu2);
        System.out.println(map.size());//1

        Set<Map.Entry<Integer,Student>>set=map.entrySet();
        for(Map.Entry<Integer,Student> node : set){
            System.out.println(node.getKey()+"="+node.getValue());
            //1=com.Collection.Student@bd308   只有一个
        }
    }
}

同时重写hashCode()和equals()方法


原因:equals方法返回true表示两个对象相同,是在同一个单向链表上比较,那么对于同一个单向链表上的节点来说,他们的哈希值(数组下标)都是相同的。所以hashCode返回的值也应该相同

6.终极结论


放在

HashMap

集合

key

部分的,以及放在

HashSet

集合中的元素,

equals()和hashCode()

方法必须同时重写,用IDEA同时生成(shift+insert)

7.哈希表总结

对于哈希表数据结构来说:

  • 如果o1和o2的哈希值相同,一定是放到同一个单项列表上

  • 如果o1和o2的哈希值不同,但由于哈希算法执行结束之后转换的数组下标有可能相同,此时发生了”哈希碰撞“。


哈希值相同一定在同一个链表上


HashMap扩容之后的容量是原容量的2倍

package com.test01;

import java.util.*;

public class test12 {
    public static void main(String[] args) {
    Students stu1 =new Students(12);
    Students stu2 = new Students(12);
        
        //创建Set集合
        Set<Students> set =new HashSet<>();
        set.add(stu1);
        set.add(stu2);
        System.out.println(stu1.equals(stu2));//重写之后返回true
        System.out.println(set.size());//1
        //同时重写equals和hashCode方法后相同的只返回一次

        //创建Map集合
        Map<Integer,Students> map =new HashMap();
        map.put(1,stu1);
        map.put(1,stu2);
        //key重复,value覆盖 
        
        System.out.println(map.size());//1

    }
}
class Students{
    private int age;
    private String name;
    public Students(){}
    public Students(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    //重写equals()和hashCode()方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) 
        return false;
        Students students = (Students) o;
        return age == students.age && Objects.equals(name, students.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }
}

8.key和value为空

HashMap()的key和value都可以为空

(面试)

package com.Collection;

import java.util.HashMap;
import java.util.Map;
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/14/9:07
 * @Description:验证map集合的key能否为空
 */
public class MapTest03 {
    public static void main(String[] args) {
        Map map = new HashMap();

        //key为null
        map.put(null,123);
        System.out.println(map.size());//1
        map.put(null,456);
        System.out.println(map.size());//1
        //value为null
        map.put(1,null);
        //map集合的key可以为空,但是只能又一个,因为会被覆盖。
        System.out.println(map.get(null));
        System.out.println(map.get(1));//null
    }
}

6-2Hashtable集合

Hashtable的key和value都不能为空(空指针异常)

Hashtable方法都带有synchronized:线程安全的。

线程安全有其他的方案,这个Hashtable对线程的处理导致效率较低,使用较少了

Hashtable和HashMap一样底层都是哈希表数据结构

Hashtable的初始化容量为11,默认加载因子是0.75

Hashtable的扩容是:原容量*2+1

6-3Properties集合

目前只需要掌握properties属性类对象

  • proprerties是一个Map集合,继承Hashtable,properties的key和value都是String类型。

  • Properties被称为属性类对象。

  • Properties是线程安全的

package com.test01;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class test13 {
    public static void main(String[] args) {
        Map M =new HashMap();
        M.put(null,null);
        System.out.println(M.size());//1
        System.out.println(M.get(null));//null
        M.put(null,100);
        System.out.println(M.get(null));//100


        Properties pro = new Properties();
        //Properties的两个方法(存、取)
        pro.setProperty("name0","chen");
        pro.setProperty("name1","liang");
        pro.setProperty("name2","jiang");

        //通过key获取value
       String s =pro.getProperty("name0");
       String s2 =pro.getProperty("name1");
       String s3 =pro.getProperty("name2");

        System.out.println(s);
        System.out.println(s2);
        System.out.println(s3);
        /*chen
          liang
          jiang
        */

    }
}

6-4TreeMap集合

1.TreeSet集合底层实际上是一个TreeMap

2.TreeMap集合底层是一个二叉树

3.放到Tree集合中的元素,等同于放到TreeMap集合Key部分了。

4.TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序

二叉树结构

7.集合工具类

Collections

java.util.Collextion: 集合接口

java.util.Collections:集合工具类

  • 排序

  • 线程安全

package com.Collection;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/16:01
 * @Description:集合工具类
 */
public class CollectionsTest {
    public static void main(String[] args) {
        //List是非线程安全的
        List<Integer> list = new ArrayList();
        //将List变为线程安全的
        Collections.synchronizedList(list);

        //排序
        list.add(465);
        list.add(789);
        list.add(159);
        Collections.sort(list);
        for(Integer lists :list){
            System.out.println(lists);
        }

        List<Tutor> lists = new ArrayList();
        lists.add(new Tutor(123));
        lists.add(new Tutor(543));
        lists.add(new Tutor(541));
        //对list元素经行排序,必须保证List集合中的元素实现了Comparable接口。
        Collections.sort(lists);
        for(Object list_1 :lists){
            System.out.println(list_1);
        }

        //对Set集合进行排序
        //将Set转成List集合
        Set<String> set = new TreeSet<>();
        set.add("abc");
        set.add("acd");
        set.add("sbs");
        set.add("abb");
        //将Set集合转成List集合
        List<String> LIST = new ArrayList<>(set);
        Collections.sort(LIST);
        for(String s : LIST){
            System.out.println(s);
        }
    }
}

class Tutor implements Comparable<Tutor>{
    int age;

    public Tutor(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Tutor o) {
        return this.age-o.age;
    }

    @Override
    public String toString() {
        return "Tutor{" +
                "age=" + age +
                '}';
    }
}


注意:Set集合可以转成List集合



版权声明:本文为weixin_67771775原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。