首页 > 其他分享 >集合汇总

集合汇总

时间:2022-10-16 22:57:01浏览次数:75  
标签:汇总 元素 list System println add 集合 out

1.集合的理解与好处

1.1数组

  1. 长度开始时必须指定,而且一旦指定,不能更改

  2. 保存的必须为同一类型的元素

  3. 使用数组进行增加、删除元素比较麻烦

    //写出Person数组的扩容示意代码
    Person[] pers=new Person[1];//定义长度为1
    pers[0]=new Person();
    
    //增加新的Person对象?
    Person[] pers2=new Person[pers.length+1];//新创建数组
    for(){}//拷贝pers数组的元素到pers2
    pers2[pers2.length-1]=new Person();//添加新的对象集合
    

1.2集合

  1. 可以动态保存任意多个对象,使用比较方便
  2. 可以提供一系列方便的操作对象的方法:add、remove、set、get等
  3. 使用集合添加、删除新元素的示意代码-简洁了

2.集合的框架体系

单列集合

image

双列集合【键值对】

image

3.Collection接口和常用方法

3.1Collection接口实现类的特点

public interface Collection<E> extends Iterable<E>
  1. Collection实现子类可以存放多个元素,每个元素可以是Object
  2. 有些Collection的实现类,可以存放重复的元素,有些不可以
  3. 有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
  4. Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

3.2Collection遍历方式

  1. Iterator迭代器

    1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素

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

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

    4. 提示:在调用iterator.next()方法之前,必须要调用iterator.hasNext()进行检查,若不调用,且下一条记录无效,则直接调用iterator.next()会抛出NoSuchElementException异常。

    5. //迭代器执行原理
      Iterator iterator = coll.iterator();//得到一个集合的迭代器
      //hasNext()://判断是否还有下一个元素
      while(iterator.hasNext()){
          //next();//①指针下移,②将下移以后集合位置上的元素返回
          Object next=iterator.next();//返回下一个元素,类型是Object
          System.out.println(iterator.next());
      }
      //生成while快捷键itit  
      
  2. 增强for循环

    1. 增强for循环,可以代替iterator迭代器,特点:增强for就是简化版的iterator,本质是一样的,增强for循环只能用于遍历集合数组

    2. 增强for循环,底层仍然是迭代器;可以debug进入for里面

    3. 基本用法

      //基本用法
      for(元素类型 元素名:集合名或数组名){
          访问元素
      }
      //增强for,用于集合上
      Collection col =new ArrayList();
      col.add(new Book(){"三国演义","罗贯中",20.2});
      col.add(new Book(){"西游记","吴承恩",18.9});
      for(Object book:col){
          System.out.println(book);
      }
      
      //增强for,用于数组上
      int[] nums={1,23,5,67,45};
      for(int i:nums){
          System.out.println(i);
      }
      

4.List接口和常用方法

4.1 List接口基本介绍

  1. List接口是Collection接口的子接口
  2. List集合类中元素有序(即添加顺序和取出顺序一致且可重复)
  3. List集合中的每个元素都有其对应的顺序索引,即支持索引【索引从0开始】
  4. List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

4.2List常用方法

以ArrayList模拟List中的方法

add()、addAll()方法

public static void main(String[] args) {
    List list=new ArrayList();
    list.add("hytour");
    list.add("cct");

    //1.在指定index位置插入元素,在hytour和cct之间插入bsm
    list.add(1,"bsm");
    System.out.println(list);//[hytour, bsm, cct]

    //2.在指定位置添加集合
    List list2=new ArrayList();
    list2.add("刀剑笑");
    list2.add("韦大宝");
    list.addAll(1,list2);//在hytour与bsm之间添加list2集合
    System.out.println(list);//[hytour, 刀剑笑, 韦大宝, bsm, cct]
}

get()方法

public static void main(String[] args) {
    //get属于 List 接口中提供方法
    List list=new ArrayList();
    list.add("hytour");
    list.add("cct");

    //获取索引为1的元素
    System.out.println(list.get(1));//cct

    //如果获取元素时,索引超过了集合的索引长度,则直接抛出异常
    Object obj=list.get(2);//抛出异常
    System.out.println(obj);
}

indexOf()、lastIndexOf()方法

public static void main(String[] args) {
    //indexOf、lastIndexOf属于 List 接口中提供方法
    List list=new ArrayList();

    list.add("刀剑笑");
    list.add("银蛟龙");
    list.add("韦大宝");
    list.add("银蛟龙");
    list.add("张三");
    list.add("银蛟龙");
    list.add("李四");

    //银蛟龙首次出现的位置,如果此集合不包含该元素,则返回 -1
    System.out.println(list.indexOf("银蛟龙"));//1
    System.out.println(list.indexOf("jh"));//-1

    //银蛟龙最后一次出现的位置,如果此集合不包含该元素,则返回 -1
    System.out.println(list.lastIndexOf("银蛟龙"));//5
    System.out.println(list.lastIndexOf("rx"));//-1
}

set()方法

public static void main(String[] args) {
    //set属于 List 接口中提供方法
    List list = new ArrayList();

    list.add("小三");
    list.add("小四");
    list.add("小五");

    System.out.println(list);//[小三, 小四, 小五]
    //将指定index位置的元素指定为当前值,将index=1位置的值设置为“刀剑笑”,但是返回值还是原来的值
    Object obj = list.set(1, "刀剑笑");
    System.out.println(obj);//小四
    System.out.println(list);//[小三, 刀剑笑, 小五]
}

subList()方法

public static void main(String[] args) {
    //subList属于 List 接口中提供方法
    List list=new ArrayList();

    list.add(1);//index=0
    list.add(2);//index=1
    list.add(3);//index=2
    list.add(4);//index=3
    list.add(5);//index=4
    list.add(6);//index=5
    list.add(7);//index=6
    list.add(8);//index=7
    list.add(9);//index=8
    list.add(10);//index=9


    //List subList(int fromIndex,int toIndex);返回从fromIndex到toIndex位置的子集合
    //注意返回的子集合 fromIndex <=subList < toIndex
    List new_list=list.subList(3,6);
    System.out.println(new_list);//[4, 5, 6]
}

isEmpty()方法

//===========声明List变量并初始化,添加元素==========================
List list = new ArrayList();

list.add("刀剑笑");
list.add("银蛟龙");
list.add(true);
list.add(10);

System.out.println(list.size());//4
System.out.println(list.isEmpty());//false,如果集合添加了元素,则返回false

//==========声明List变量并初始化,未添加元素===========================
List list2 = new ArrayList();
System.out.println(list2.size());//0
System.out.println(list2.isEmpty());//true,如果集合未添加任何元素,则返回true

//==========声明List变量未初始化===========================
List list3=null;//定义集合list3未进行初始化操作
System.out.println(list3.size());//如果list3是null,直接调用list3.size()则会报异常
System.out.println(list3.isEmpty());//如果list3是null,直接调用list3.isEmpty()则会报异常

clear()方法

List list = new ArrayList();

list.add("刀剑笑");
list.add("银蛟龙");
list.add(true);
list.add(10);

System.out.println(list.size());//4
System.out.println(list.isEmpty());//false,如果集合添加了元素,则返回false

list.clear();//list进行clear之后,是一个空集合,不是null

System.out.println(list.size());//0
System.out.println(list);//[]
System.out.println(list.isEmpty());//true

addAll()方法

List list = new ArrayList();

list.add("xiaosan");
list.add("刀剑笑");
list.add(123);
System.out.println(list);//[xiaosan, 刀剑笑, 123]

List list2 = new ArrayList();
list2.add("三国演义");
list2.add("西游记");
list2.add(123);

list.addAll(list2);//将集合list2的所有元素都添加到集合list中
System.out.println(list);//[xiaosan, 刀剑笑, 123, 三国演义, 西游记, 123]

contains()方法

public static void main(String[] args) {
    List list = new ArrayList();

    list.add("热血江湖");
    list.add("CF");

    //contains  list存在则返回true,list不存在则返回false  【严格区分大小写】
    
    boolean res = list.contains("Cf");
    System.out.println(res);//false
    boolean res2 = list.contains("CF");
    System.out.println(res2);//true
}

containsAll()方法

//boolean containsAll(Collection c)	判断集合中是否包含集合 c 中的所有元素
List list = new ArrayList();

list.add("xiaosan");
list.add("刀剑笑");
list.add(123);

System.out.println(list);//[xiaosan, 刀剑笑, 123]
List list2 = new ArrayList();
list2.add("三国演义");
list2.add("西游记");
list2.add(123);

list.addAll(list2);
System.out.println(list);//[xiaosan, 刀剑笑, 123, 三国演义, 西游记, 123]

//==========list3中的元素“红楼梦”,不在list中,所以返回false==========
List list3 = new ArrayList();
list3.add("三国演义");
list3.add("西游记");
list3.add("红楼梦");
System.out.println(list3);//[三国演义, 西游记, 红楼梦]
System.out.println(list.containsAll(list3));//false  如果list3的所有元素都在list中,则返回true;只要list3中有一个元素不在list中,则返回false

//==========list3中的元素全部都在list中,所以返回true==========
List list3 = new ArrayList();
list3.add("三国演义");
list3.add("西游记");
System.out.println(list3);//[三国演义, 西游记]
System.out.println(list.containsAll(list3));//true  如果list3的所有元素都在list中,则返回true;只要list3中有一个元素不在list中,则返回false

remove()方法

public static void main(String[] args) {
    List list =new ArrayList();

    list.add("三国演义");
    list.add("西游记");
    list.add("红楼梦");
    list.add("水浒传");

    //删除指定index位置的元素,并返回此元素
    Object obj=list.remove(0);//删除索引为0的元素
    System.out.println(obj);//三国演义
    System.out.println(list);//[西游记, 红楼梦, 水浒传]

    //删除指定的元素,删除成功返回true,否则返回false
    Object obj2=list.remove("红楼梦");
    System.out.println(obj2);//true
    System.out.println(list);//[西游记, 水浒传]

    //====================================================
    //如果集合中包含多个相同的元素,根据指定元素删除时,删除的只是第一次出现的元素
    List list =new ArrayList();

    list.add("三国演义");
    list.add("西游记");
    list.add("水浒传");
    list.add("红楼梦");
    list.add("水浒传");
    list.add("热血江湖");

    System.out.println(list);//[三国演义, 西游记, 水浒传, 红楼梦, 水浒传, 热血江湖]
    list.remove("水浒传");
    System.out.println(list);//[三国演义, 西游记, 红楼梦, 水浒传, 热血江湖]
}

removeAll()方法

//boolean removeAll(Collection c)	从集合中删除所有在集合 c 中出现的元素(相当于把调用该方法的集合减去集合 c)。如果该操作改变了调用该方法的集合,则该方法返回 true。
List list=new ArrayList();

list.add(123);
list.add("小三");
list.add("西游记");
list.add("三国演义");
list.add("刀剑笑");
list.add("三国演义");
System.out.println(list);//[123, 小三, 西游记, 三国演义, 刀剑笑, 三国演义]

//===========list2集合中的元素都在list集合中========
List list2=new ArrayList();
list2.add("三国演义");
list2.add("刀剑笑");
System.out.println(list2);//[三国演义, 刀剑笑]

//如果list2中的元素,在list中出现多个,则list中的多个元素都会被删除,比如:三国演义
System.out.println(list.removeAll(list2));//true
System.out.println(list);//[123, 小三, 西游记]

//===========list3集合中的元素不都在list集合中========
List list3=new ArrayList();
list3.add("三国演义");
list3.add("刀剑笑");
list3.add("红楼梦");
System.out.println(list3);//[三国演义, 刀剑笑, 红楼梦]

//如果list3中的元素,部分出现在list集合中,则在list中的元素会被删除,如果出现多个,则多个都会被删除,比如:三国演义
System.out.println(list.removeAll(list3));//true
System.out.println(list);//[123, 小三, 西游记]

 //===========list4集合中的元素都不在list集合中,则返回false========
List list4=new ArrayList();
list4.add("热血江湖");
list4.add("CF");
System.out.println(list4);

//如果list4中有一个元素在list集合中,则返回true;如果list4中的所有元素都不在list集合中,则返回false
System.out.println(list.removeAll(list4));//false
System.out.println(list);//[123, 小三, 西游记, 三国演义, 刀剑笑, 三国演义]

retainAll()方法

public static void main(String[] args) {
    //boolean retainAll(Collection c)  从集合中删除集合 c 里不包含的元素(相当于把调用该方法的集合变成该集合和集合 c 的交集),
    // 如果该操作改变了调用该方法的集合,则该方法返回 true。
    List list = new ArrayList();

    list.add("三国演义");
    list.add("红楼梦");
    list.add("西游记");
    list.add("水浒传");
    System.out.println(list);//[三国演义, 红楼梦, 西游记, 水浒传]

    List list2 = new ArrayList();
    list2.add("三国演义");
    list2.add("西游记");
    System.out.println(list2);//[三国演义, 西游记]

    boolean res = list.retainAll(list2);
    System.out.println(res);//true
    System.out.println(list);//[三国演义, 西游记]  因为c集合中不包含“红楼梦"、"水浒传" 所以会把这两项删除了
}

4.3List的三种遍历方式

List的三种实现[ArrayList、LinkedList、Vector]

//这是一个程序入口
public static void main(String[] args) {
    List list=new ArrayList();

    list.add(123);
    list.add("门柱");
    list.add("热血江湖");
    list.add("西游记");
    list.add("person");

    //====================迭代器循环==============================
    Iterator iterator = list.iterator();
    //快捷键itit
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        System.out.println(obj);
    }
    
    //====================增强for循环==============================
    //快捷键大写字母I
    for (Object obj:list) {
        System.out.println(obj);
    }

    //====================普通for循环==============================
    //快捷键fori
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

4.4集合冒泡排序

public class Book{
    public String name;
    public String author;
    public double price        
}
//要求价格由小到大排序
public static void sort(List list){
    int listSize = list.size();
    for(int i = 0;i < listSize-1;i++){
        for(int j=0;j<listSize-1-i;j++){
            Book book1 = (Book)list.get(j);
            Book book2 = (Book)list.get(j+1);
            if(book1.getPrice()>book2.getPrice()){
                list.set(j,book2);
                list.set(j+1,book1);
            }
        }
    }
}

5.ArrayList底层结构和源码分析

5.1ArrayList的注意事项

  1. ArrayList可以添加任何元素,包括null,可以加入多个null
  2. ArrayList是由数组来实现数据存储的
  3. ArrayList是线程不安全的(执行效率高),在多线程情况下,不建议使用ArrayList

5.2ArrayList的底层操作机制源码分析

  1. ArrayList中维护了一个Object类型的数组elementData

    transient Object[] elementData;//transient 修饰的元素不会被序列话,比如ArrayList被序列化时,elementData属性不会被序列化
    
  2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加元素时,则扩容elementData为10,如果再次扩容,则扩容elementData为1.5倍。

    0->10->10 * 1.5=15->15 * 1.5 = 22 ->22 * 1.5 =33

  3. 当创建ArrayList对象时,如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍

    ArrayList arrayList = new ArrayList(5);//elementData容量初始大小为5
    
  4. 数组保留原先数据扩容Arrays.copyOf

    int arr = {1,2,3,4,5};
    arr = Arrays.copyOf(arr,10);//将arr扩容,由长度为5扩容到长度为10
    //此时arr的内容为
    {1,2,3,4,5,0,0,0,0,0}
    
  5. 具体源码跟踪可参考

    关于ArrayList源码跟踪 - 南晓东 - 博客园 (cnblogs.com)

6.Vector底层结构和源码剖析

6.1Vctor的基本介绍

  1. Vector的定义

    public class Vector<E>
        extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    
  2. Vector底层也是一个对象数组

    protected Object[] elementData;
    
  3. Vector是线程同步的,即线程安全的,Vector类的操作方法带有synchronized关键字,比如:get

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

6.2Vector与ArrayList的比较

底层结构 版本 线程安全(同步)效率 扩容倍数
ArrayList 可变数组 jdk1.2 不安全,效率高 如果有参构造1.5倍;如果是无参,1.第一次10,2.从第二次开始按1.5倍扩容
Vector 可变数组 jdk1.0 安全,效率不高 如果是无参,默认是10,满后就按2倍扩容;如果有参数指定大小,则每次直接按2倍扩容

7.LinkedList底层结构

7.1LinkedList底层操作机制

  1. 可以添加任意元素(元素可以重复),包括null
  2. 线程不安全,没有实现同步
  3. LinkedList底层维护了一个双向链表
  4. LinkedList中维护了两个属性first和last分别指向首节点和尾节点
  5. 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个节点,通过next指向后一个节点,最终实现双向链表
  6. LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高

7.2源码分析

  1. 内部结构

    //定义了一个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;
        }
    }
    
    //定义了主要属性
    transient int size = 0;
    transient Node<E> first;
    transient Node<E> last;
    
  2. 添加元素,add()方法

    //执行初始化操作
    LinkedList linkedList = new LinkedList();
    //内部执行
    public LinkedList(){}  //此时linkedLast的属性  first=null  last=null
    
    //执行添加元素操作
    linkedList.add(1);
    
    //内部执行
     public boolean add(E e) {
         linkLast(e);
         return true;
     }
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    
  3. 删除元素,remove()方法

    linkedList.remove();//默认删除第一个元素
    linkedList.remove(index);//删除指定索引的元素
    linkedList.remove(Object);//删除指定的元素
    
    //=================================源码分析=====================================
    linkedList.remove(index);//删除指定索引的元素
    
    //内部执行
    public E remove(int index) {
        checkElementIndex(index);//检查索引是否正常
        return unlink(node(index));//1.根据索引获取到元素   2.调用删除方法
    }
    
    //检查索引是否正常
    private void checkElementIndex(int index) {
        if (!isElementIndex(index))//判断是否为链表索引
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    //判断是否为链表索引
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }
    
    //根据索引获取到链表中的元素
    Node<E> node(int index) {
        // assert isElementIndex(index);
    	//非常巧妙的 中间分组算法
        if (index < (size >> 1)) {//size >> 1 =>size/2
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;   //如果index=5,循环只能执行到i=4,此时x.next就相当于是i=5的元素
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
    
    //调用删除方法
    E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;
    
        //prev == null说明x是第一个元素,如果要删除第一个元素,则需要把first指向第二个元素,即x.next
        if (prev == null) {
            first = next;
        } else {
            prev.next = next;//前一个元素的后一个结点,指向x的下一个结点,把x这个要删除的结点跳过
            x.prev = null;//当前要删除的x结点,就不需要指向前一个结点了
        }
    	//next == null 说明x是最后一个元素,如果要删除最后一个元素,则需要把last指向倒数第二个元素,即x.prev
        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;//后一个元素的前一个结点,指向x的前一个结点,把x这个要删除的结点跳过
            x.next = null;//当前要删除的x结点,就不需要指向后一个结点了
        }
    
        x.item = null;//将当前要删除的x结点,置为null
        size--;//链表元素总个数减一
        modCount++;//修改次数+1
        return element;
    }
    
  4. 修改元素,set()方法

    //LinkedList修改某个结点对象
    linkedList.set(2,"xiaosi");
    
    
    //循环方式,因为LinkedList实现了List接口,遍历方式
    //1.迭代器循环->快捷键itit
    Iterator iterator = linkedList.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        System.out.println(obj);            
    }
    //2.增强for循环->快捷键大写字母I
    for (Object obj :linkedList) {
        System.out.println(obj);
    }
    //3.普通for循环
    for (int i = 0; i < linkedList.size(); i++) {
        Object obj=linkedList.get(i);
        System.out.println(obj);
    }
    
  5. 获取元素,get()方法

    //得到LinkedList的第二个对象
    Object obj=linkedList.get(1);
    
  6. LInkedList循环

    //循环方式,因为LinkedList实现了List接口,遍历方式
    //1.迭代器循环->快捷键itit
    Iterator iterator = linkedList.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        System.out.println(obj);            
    }
    //2.增强for循环->快捷键大写字母I
    for (Object obj :linkedList) {
        System.out.println(obj);
    }
    //3.普通for循环
    for (int i = 0; i < linkedList.size(); i++) {
        Object obj=linkedList.get(i);
        System.out.println(obj);
    }
    

7.3模拟双向链表

//定义一个Node类,Node 对象 表示双向链表的一个结点
public class Node{
    public Object item;//真正存放数据
    public Node next;//指向后一个结点
    public Node pre;//指向前一个结点
    public Node(Object name){
        this.item = name;
    }
    public String toString(){
        return "Node name="+item;
    }
}
public static void main(String[] args){
    //模拟一个简单的双向链表
    Node jack = new Node("jack");
    Node tom = new Node("tom");
    Node xiaosan = new Node("xiaosan");
    
    //连接三个结点,形成双向链表
    //jack -> tom ->xiaosan
    jack.next = tom;
    tom.next = xiaosan;
    //xiaosan -> tom -> jack
    xiaosan.pre = tom;
    tom.pre = jack;
    
    //定义双向链表的头结点
    Node first = jack;//让first引用指向jack
    
    //定义双向链表的尾结点
    Node last = xiaosan;//让last引用指向xiaosan
    
    //从头到尾进行遍历
    while(true){
        if(first == null){
            break;
        }
        //输出first信息
        System.out.println(first);
        first = first.next;//需要重点理解
    }
    
    //从尾到头进行遍历
    while(true){
        if(last == null){
            break;
        }
        //输出last信息
        System.out.println(last);
        last = last.pre;//需要重点理解
    }
    
    //在tom和xiaosan之间,插入一个对象   smith
    //1.先创建一个Node结点,name就是smith
    Node smith = new Node("smith");
    //2.下面就把smith加入到双向链表了
    smith.next=xiaosan;
    smith.pre=tom;
    xiaosan.pre = smith;
    tom.next = smith;
}

8.ArrayList和LinkedList比较

底层结构 增删效率 改查效率 线程安全
ArrayList 可变数组 较低,数组扩容 较高 线程不安全
LinkedList 双向链表 较高,通过链表追加 较低 线程不安全

如何选择ArrayList和LinkedList:

  1. 如果改查的操作较多,选择ArrayList
  2. 如果增删的操作多,选择LinkedList

9.Set接口和常用方法

9.1Set接口基本介绍

  1. 无序(添加和取出的顺序不一样),没有索引
  2. 不允许重复元素,最多包含一个null
  3. 注意:取出的顺序虽然不是添加的顺序,但是取出的顺序是固定的

9.2Set接口的常用方法

  1. 和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样

9.3Set接口的遍历方式

  1. 可以使用迭代器
  2. 增强for循环
  3. 不能使用索引的方式来获取【不能使用普通for循环】

10.Set接口实现类-HashSet

10.1HashSet全面说明

  1. HashSet实现了Set接口

  2. HahSet实际上是HashMap

    public HashSet(){
        map = new HashMap<>();
    }
    
  3. 可以存放null值,但是只能存放一个null

  4. HashSet不能保证元素是有序的,取决于hash后,再确定索引的结果

  5. 不能有重复元素/对象

10.2HashSet常用方法

HashSet set =new HashSet();

//在执行add方法后,会返回一个boolean值;如果添加成功,返回true,否则返回false
boolean res = set.add("rxjh");//true
boolean res1 = set.add("rxjh");//false

set.add(new Dog("tom"));//true
set.add(new Dog("tom"));//true

set.add(new String("jack"));//true
set.add(new String("jack"));//false

10.3模拟数组+链表

//结点,存储数据,可以指向下一个结点,从而形成链表
class Node{
    Object item;//存放数据
    Node next;//指向下一个结点
    public Node(Object item,Node next){
        this.item=item;
        this.next=next;
    }
}

//模拟一个HashMap的底层
public static void main(String[]args){
    //1.创建一个数组,数组的类型是Node[]
    Node [] table = new Node[16];
    
    //2.创建结点
    Node join=new Node("join",null);
    table[2]=join;//将join放在table表的索引为2的位置
    
    Node jack= new Node("jack",null);
    join.next=jack;//将jack结点挂载到join
    
    Node rose= new Node("rose",null);
    jack.next=rose;//将rose结点挂载到jack
    
    Node lucy = new Node("lucy",null);
    table[3]=lucy;//将lucy放到table表的索引为3的位置    
}

10.4HashSet底层机制

  1. HashSet底层是HashMap,HashMap底层是(数组+链表+红黑树)【单项链表】
  2. 添加一个元素时,先得到hash值-会转成->索引值
  3. 找到存储数据表table,看这个索引位置是否已经存放的有元素
  4. 如果没有直接添加
  5. 如果有,调用equals比较,如果相同就放弃添加,如果相同则添加到最后
  6. 在java8中,如果一个链表的元素个数到TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
public static void main(String[] args) {
    HashSet hashSet=new HashSet();
    hashSet.add("java");
    hashSet.add("php");
    hashSet.add("java");
}
//===============================源码=============================
//HashSet类中,维护变量信息
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();

//1.执行构造器 new HashSet();
public HashSet() {
    map = new HashMap<>();//底层是HashMap
}
//2.执行add("java");
public boolean add(E e) {  //E为泛型,e就是添加的元素,第一个add时,e就是java字符串
    return map.put(e, PRESENT)==null;
}
//3.以下代码已经进入到了HashMap类里面==============
public V put(K key, V value) {//key就是添加的java字符串;value就是PRESENT对象,起一个占位作用,为了使HashSet使用到HashMap,value放的统一都是object
    return putVal(hash(key), key, value, false, true);
}
//计算hash值,就是table的索引值
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//实际添加元素核心代码【重点核心】
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;//定义了辅助变量
    //table就是HashMap的一个数组,类型是Node[]
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;//table表的第一次扩容,n=16
    //(1)根据key计算的hash,去计算key应该存放到table表的哪个索引位置,并把这个位置的对象,赋给p
    //(2)如果p为null,表示还没有存放元素,就创建一个Node放在tabl[i]这个位置
    if ((p = tab[i = (n - 1) & hash]) == null)//(n-1)即索引从0-15
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        //如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样
        //(1)准备加入的key和p指向的Node结点的key是同一个对象
        //(2)p指向的Node结点的key的equals()和准备加入的key比较后相同
        //如果满足这两个条件中的任意一个,就不加入
        if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        //判断p是不是一个红黑树,如果是,则调用putTreeVal,来进行添加
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            //如果table对应的索引位置,已经是一个链表,就使用for循环比较
            for (int binCount = 0; ; ++binCount) {//这个for循环没有限制条件,其实是个死循环
                //依次和链表中的每一个元素比较后,都不相同,则加入到该链表的最后
                if ((e = p.next) == null) {//如果第一次就满足的话,说明链表中就一个元素
                    p.next = newNode(hash, key, value, null);
                    //注意:把元素添加到链表后,立即判断 该链表是否已经达到8个结点,如果达到就调用treeifyBin()对当前这个链接进行树化,转成红黑树【在转成红黑树时,还进行一个判断,如果table长度小于64不会进行树化,只是进行table数组扩容】
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                //依次和该链表的每一个元素比较过程中,如果有相同情况,就直接break
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
              //for中把p.next给了e,相当于e是p指向的下一个结点;此处又把e给了p相当于p向下移动了一个结点
                p = e;
            }
        }
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
        }
        ++modCount;
	    //size 就是没加入一个结点的Node(k,v,h,next) 无论结点是加在table中某个索引的第一个元素,还是某个索引的链表上,只要加入Node元size就会++【只要size到达12就会扩容】
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);//目的是让Hashmap得子类去实现的
        return null;//添加之后,返回null
    }

10.5HashSet扩容机制和转成红黑树机制

  1. HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75=12
  2. 如果table数组使用到了临界值12,就会扩容到16*2=32---->32 * 2=64,新的临界值就是32 * 0.75 =24---->64 * 0.75 =48,依次类推
  3. 在java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制
//如何能for循环将所有的数据添加到同一个链表上 1.保证hash相同 2.key值不同
class A{
    private int n;
    
    public A(int n){
        this.n = n;
    }
    @Override
    public int hashCode(){
        return 100;//A的所有对象,hash都返回100
    }
}   
public static void main(String[] args){
    HashSet hashSet = new HashSet();
    for (int i=1;i<=12;i++){
        hashSet.add(new A(i));//equals()不同
    }
}
//for循环8次,即i=8时,此时所有的元素都在table[4]这个位置形成一个链表,链表的个数为8个
//for再循环一次,即i=9时,链表元素大于8,触发树化操作,但是table的长度没有到64【此时table的长度为32,16->32】,所以只对table的长度进行了扩容,链表没有树化【此时这个链表上的数据为9个,链表在table的索引位置变成了table[8]】
//for再循环一次,即i=10时,链表元素大于8,触发树化操作,但是table的长度没有到64【此时table的长度为64,32->64】,所以只对table的长度进行了扩容,链表没有树化【此时这个链表上的数据为10个,链表在table的索引位置变成了table[32]】
//for再循环一次,即i=11时,链表元素大于8,触发树化操作,同时满足了数组长度不小于64且链表长度大于等于8.则对该链表进行树化

11.Set接口实现类-LinkedHashSet

11.1LinkedHashSet全面说明

  1. LinkedHashSet是HashSet的子类
  2. LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表【LinkedHashMap是HashMap的一个子类】
  3. LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的【插入的顺序与查询的顺序相同】
  4. LinkedHashSet不允许添加重复元素

11.2LinkedHashSet底层机制

img

12.TreeSet

与HashSet最大的区别是,TreeSet可以排序【默认情况下,不做任何处理TreeSet也是无序的】

12.1当使用TreeSet的无参构造器,创建TreeSet时,仍然是无序的

public static void main(String[] args) {
   TreeSet treeSet = new TreeSet();
    treeSet.add("tom");
    treeSet.add("lili");
    treeSet.add("jack");
    treeSet.add("a");
    System.out.println(treeSet);//[a, jack, lili, tom]
}

12.2使用TreeSet的一个构造器可以传入一个比较器(匿名内部类)并指定排序规则

public static void main(String[] args) {
    TreeSet treeSet = new TreeSet(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            //调用String的compareTo方法进行字符串大小的比较
            return ((String)o1).compareTo((String)o2);
        }
    });
    treeSet.add("tom");
    treeSet.add("lili");
    treeSet.add("jack");
    treeSet.add("a");
    System.out.println(treeSet);//[a, jack, lili, tom]
}

12.3使用Treeset添加一个对象

//=====================================发生异常情况========================================================
class  Person{}
public static void main(String[] args) {

    TreeSet treeSet1 = new TreeSet();
    treeSet1.add(new Person());//会抛出异常,原因是Person没有实现Comparator接口
}
//=====================================正常情况========================================================
class  Person implements Comparable{
    @Override
    public int compareTo(Object o) {
        return 0;
    }
}
public static void main(String[] args) {
    TreeSet treeSet1 = new TreeSet();
    treeSet1.add(new Person());//正常添加
}

13.Map接口和常用方法

13.1Map实现类的特点

  1. Map用于保存具有映射关系的数据: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
//如果添加相同key的数据,后添加的key的数据会把先添加的key的数据覆盖掉
Map map=new HashMap();
map.put("no1","刀剑笑");
map.put("no2","银蛟龙");
map.put("no1","韦大宝");
//最终结果只有两个元素,即{no2=银蛟龙,no1=韦大宝}

13.2常用方法

public static void main(String[] args){
    //map常用方法
    Map map=new HashMap();
    //put:添加元素
    map.put("no1","韦大宝");
    
    //remove:根据键删除映射关系
    map.remove("no1");
    
    //get:根据键获取值
    Object val=map.get("no1");//韦大宝
    
    //size:获取元素个数
    int size = map.size();
    
    //isEmpty:判断个数是否为0
    boolean bol=map.isEmpty();
    
    //clear:清除k-v
    map.clear();//void类型,无返回值
    
    //containsKey():查找键是否存在
    boolean no11 = map.containsKey("no1");//true

    //containsValue():查找值是否存在
    boolean nxd = map.containsValue("nxd");//true    
}

13.3遍历方式

创建map并输入map数据

Map map=new HashMap();
map.put("吴承恩","西游记");
map.put("罗贯中","三国演义");
map.put("施耐庵","水浒传");
map.put("曹雪芹","红楼梦");

System.out.println(map);//{吴承恩=西游记, 罗贯中=三国演义, 曹雪芹=红楼梦, 施耐庵=水浒传}

获取map所有的key

//获取map所有的key
Set keySet = map.keySet();
System.out.println(keySet);//[吴承恩, 罗贯中, 曹雪芹, 施耐庵]

获取map所有的value

//获取map所有的value
Collection values = map.values();
System.out.println(values);//[西游记, 三国演义, 红楼梦, 水浒传]

通过keySet循环

//①先取出所有的key,通过key取出对应的value
Set keySet=map.keySet();
System.out.println("==================keySet()方式-增强for======================");
//增强for循环【快捷键大写I】
for (Object key :keySet) {
    //吴承恩-西游记
    //罗贯中-三国演义
    //曹雪芹-红楼梦
    //施耐庵-水浒传
    System.out.println(key+"-"+map.get(key));
}
System.out.println("==================keySet()方式-迭代器======================");
//迭代器循环【快捷键itit】
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
    Object key =  iterator.next();
    System.out.println(key+"-"+map.get(key));
}

System.out.println("==================keySet()方式-普通for循环======================");
//普通for循环【不支持】
for (int i = 0; i < keySet.size(); i++) {
    //System.out.println(keySet.get(i));//keySet没有get()方法,不能进行普通for循环
}

通过values循环

//②取出所有的values
Collection values = map.values();
System.out.println("==================values()方式-增强for======================");
for (Object value :values) {
    //西游记
    //三国演义
    //红楼梦
    //水浒传
    System.out.println(value);
}
System.out.println("==================values()方式-迭代器======================");
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()) {
    //西游记
    //三国演义
    //红楼梦
    //水浒传
    Object value =  iterator1.next();
    System.out.println(value);
}
System.out.println("==================values()方式-普通for循环======================");
//普通for循环【不支持】
for (int i = 0; i < values.size(); i++) {
    //System.out.println(values.get(i));//values没有get()方法,不能进行普通for循环
}

通过EntrySet循环

//③通过EntrySet来获取k-v
Set entrySet = map.entrySet();
//迭代器循环
Iterator iterator2 = entrySet.iterator();
while (iterator2.hasNext()) {
    Object entry  = iterator2.next();
    //System.out.println(next.getClass());//HashMap$Node没有getKey()、getValue()方法,HashMap$Node 实现->Map.Entry(getKey,getValue)
    //向下转型
    Map.Entry m=(Map.Entry)entry;
    System.out.println(m.getKey()+"-"+m.getValue());
}
//增强for循环
for (Object entry :entrySet) {
    //将entry转成Map.Entry【entry是没有getKey()方法、getValue()方法的】
    Map.Entry m=(Map.Entry)entry;
    System.out.println(m.getKey()+"-"+m.getValue());
}
//普通for循环【不支持】
for (int i = 0; i < entrySet.size(); i++) {
    //Object entry=entrySet.get(i);//entrySet没有get()方法,不能进行普通for循环
}

14.Map接口实现类-HashMap

14.1HashMap小结

  1. HashMap是Map接口使用频率最高的实现类
  2. HashMap是以key-val 键值对方式来存储数据(HashMap$Node类型)
  3. key不能重复,但是值可以重复,允许使用null键和null值;注意key为null只能有一个,value为null可以有多个
  4. 如果添加相同的key,则会覆盖原来的key-val,等同于修改(key不会替换,val会替换)
  5. 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的(jdk7.0数组+链表,jdk8.0的hashMap底层 数组+链表+红黑树)
  6. HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized

14.2HashMap底层机制

image-20221013222754315

14.3HashMap扩容机制

扩容机制和HashSet相同

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

    transient Node<K,V>[] table;
    
  2. 当创建对象时,将加载因子(loadfactor)初始化为0.75

    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    public HashMap() {
    	this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
    
  3. 当添加key-val时,通过key的hash值得到在table的索引。然后判断该索引处是否有元素,如果没有元素则直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等则直接替换val;如果不相等,则需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。

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

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

  6. 在java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),该链表就会进行树化(红黑树)【该链表这句需要验证】

15.Map接口实现类-HashTable

15.1基本介绍

  1. 存放的元素是键值对:即K-V
  2. HashTable的键和值都不能为null,否则会抛出NullPointerException
  3. HashTable使用方法基本上和HashMap一样
  4. HashTable是线程安全的(synchronized),HashMap是线程不安全的

15.2基本使用

public static void main(String[] args) {
    Hashtable hashtable = new Hashtable();
    hashtable.put("join",100);//ok
    //hashtable.put(null,100);//NullPointerException   键和值都不能为null
    //hashtable.put("join",null);//NullPointerException		键和值都不能为null
    hashtable.put("lic",100);//ok
    hashtable.put("lic",100);//替换
}

15.3HashTable与HashMap对比

版本 线程安全(同步) 效率 允许null键null值
HashMap 1.2 不安全 可以
HashTable 1.0 安全 较低 不可以

16.Map接口实现类Properties

16.1基本介绍

  1. Properties类继承自HashTable类并且实现了Map接口,也是使用一种键值对的形式来保存数据
  2. 使用特点与HashTable类似
  3. Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改

16.2常用方法

public static void main(String[] args) {
    Properties properties = new Properties();
    properties.put("join", 100);//ok
    //properties.put(null,100);//NullPointerException
    //properties.put("join",null);//NullPointerException

    properties.put("lic", 100);//ok
    properties.put("lic", 88);//替换
    System.out.println(properties);//{lic=88, join=100}
    //删除
    properties.remove("lic");
    System.out.println(properties);//{join=100}

    //查询
    System.out.println(properties.get("join"));//100
    properties.put("lucy", 110);
    System.out.println(properties.getProperty("lucy"));//null【这个返回null,需要注意】
}

17.Map接口实现类-TreeMap

17.1小结

  1. TreeMap是TreeSet的底层实现

  2. TreeMap可以按照key进行排序【默认情况下,不做任何处理的TreeMap也是无序的】

  3. 键不能为null,值可以null且可以有多个

  4. 当使用TreeMap的无参构造器,创建TreeMap时,仍然是无序的

    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap();
        treeMap.put("jack","杰克");
        treeMap.put("tom","汤姆");
        treeMap.put("kiss","kkkk");
        treeMap.put("smith","斯密斯");
    
        System.out.println(treeMap);//{jack=杰克, kiss=kkkk, smith=斯密斯, tom=汤姆}
    }
    
  5. 使用TreeMap的一个构造器可以传入一个比较器(匿名内部类)并指定排序规则

    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                //按照key由小到大排序
                //return ((String)o1).compareTo((String) o2);//如果返回0的话,value做替换操作
                //按照key的长度大小排序
                return ((String)o1).length()-((String)o2).length();  //如果返回0的话,value做替换操作
            }
        });
        treeMap.put("jack","杰克");
        treeMap.put("tom","汤姆");
        treeMap.put("kiss","kkkk");
        treeMap.put("smith","斯密斯");
    
        System.out.println(treeMap);//{tom=汤姆, jack=kkkk, smith=斯密斯}    
        //重点解释:为什么key为kiss的元素值没有添加进来,key为jack的元素值被替换为了key为kiss的值?
        //因为构造器中,指定的匿名内部类,是按照key字符串长度大小进行排序的,如果判断key的字符串长度相等的话,则值做替换操作
    }
    
  6. TreeMap的key必须实现Comparator接口

    //=====================================发生异常情况========================================================
    class  Person{}
    public static void main(String[] args) {
    
        TreeMap treeMap = new TreeMap();
        treeMap.put(new Person(),"213");//使用匿名person对象作为key直接抛出异常,原因是Person没有实现Comparator接口
    }
    //=====================================正常情况========================================================
    class  Person implements Comparable
    {
        @Override
        public int compareTo(Object o) {
            return 0;
        }
    }
    public static void main(String[] args) {
    
        TreeMap treeMap = new TreeMap();
        treeMap.put(new Person(),"213");//正常添加
    }
    
    

18.集合汇总

如何选择集合实现类

  1. 先判断存储的类型(一组对象【单列】或一组键值对【双列】)
  2. 一组对象【单列】:Collection接口
    1. 允许重复:List
      1. 增删多:LinkedList【底层维护了一个双向链表】
      2. 改查多:ArrayList【底层维护了Object类型的可变数组】
    2. 不允许重复Set
      1. 无序:HashSet【底层是HashMap,维护了一个哈希表 即(数组+链表+红黑树)】
      2. 排序:TreeSet
      3. 插入和取出顺序一致:LinkedHashSet【底层是LinkedHashMap的底层是HashMap】,维护数组+双向链表
  3. 一组键值对【双列】:Map
    1. 键无序:HashMap【底层是:哈希表 jdk7:数组+链表 jdk8:数组+链表+红黑树】
    2. 键排序:TreeMap
    3. 键插入和取出顺序一致:LinkedHashMap【底层是:数组+双向链表】
    4. 读取文件 :ProPerties

19.Collections工具类

19.1基本介绍

  1. Collections是一个操作Set、List和Map等集合的工具类
  2. Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作

19.2排序操作(均为静态方法)

  1. reverse(List):反转List中元素的顺序
  2. shuffle(List):对List集合元素进行随机排序
  3. sort(List):根据元素的自然顺序对指定List集合元素按升序排序
  4. sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
  5. swap(List,int,int):将指定List集合中的i处元素和j处元素进行交换
public static void main(String[] args) {
    List list = new ArrayList();
    list.add("tom");
    list.add("smith");
    list.add("king");
    list.add("milan");

    System.out.println(list);//[tom, smith, king, milan]

    //reverse(List):反转List中元素的顺序
    Collections.reverse(list);
    System.out.println(list);//[milan, king, smith, tom]

    //shuffle(List):对List集合元素进行随机排序
    Collections.shuffle(list);//[milan, smith, tom, king]  每次顺序都不一样
    System.out.println(list);
    Collections.shuffle(list);//[tom, milan, smith, king]  每次顺序都不一样
    System.out.println(list);

    //sort(List):根据元素的自然顺序对指定List集合元素按升序排序
    Collections.sort(list);
    System.out.println("自然排序:"+list);//自然排序:[king, milan, smith, tom]
    //希望按照字符串的长度大小排序
    Collections.sort(list, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            //if(o1 instanceof  String)  可以加上这样的判断
            return ((String)o1).length()-((String)o2).length();
        }
    });
    System.out.println("按照字符长度大小排序:"+list);//按照字符长度大小排序:[tom, king, milan, smith]

    //swap(List,int,int):将指定List集合中的i处元素和j处元素进行交换
    System.out.println("交换前="+list);//交换前=[tom, king, milan, smith]
    Collections.swap(list,0,1);
    System.out.println("交换后="+list);//交换后=[king, tom, milan, smith]
}

19.2查找、替换

  1. Object max(Collection):根据元素的自然顺序,返回给定集合中最大元素
  2. Object max(Collection Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
  3. Object min(Collection)
  4. Object min(Collection Comparator)
  5. int frequency(Collection,Object):返回指定集合中指定元素的出现次数
  6. void copy(List dest,List src):将src中的内容复制到dest中
  7. boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List对象的所有旧值
 public static void main(String[] args) {
     List list = new ArrayList();
     list.add("tom");
     list.add("smith");
     list.add("king");
     list.add("milan");

     System.out.println(list);//[tom, smith, king, milan]

     //Object max(Collection):根据元素的自然顺序,返回给定集合中最大元素
     System.out.println("自然顺序最大元素=" + Collections.max(list));//自然顺序最大元素=tom

     //Object max(Collection Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
     //比如,我们要返回长度最大的元素
     Object maxObject = Collections.max(list, new Comparator() {
         @Override
         public int compare(Object o1, Object o2) {
             return ((String) o1).length() - ((String) o2).length();
         }
     });
     System.out.println("长度最大的元素=" + maxObject);//长度最大的元素=smith

     //int frequency(Collection,Object):返回指定集合中指定元素的出现次数
     int tom_num = Collections.frequency(list, "tom");
     System.out.println("tom出现的次数=" + tom_num);//tom出现的次数=1

     //void copy(List dest,List src):将src中的内容复制到dest中
     ArrayList dest = new ArrayList();
     //Collections.copy(dest,list);
     //System.out.println("dest="+dest);//异常:Source does not fit in dest
     //为了完成一个完整拷贝,我们需要先给dest赋值,大小和list.size()一样
     for (int i = 0; i < list.size(); i++) {
         dest.add("");
     }
     //拷贝
     Collections.copy(dest,list);
     System.out.println("dest="+dest);//dest=[tom, smith, king, milan]

     //boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List对象的所有旧值
     list.add("tom");
     System.out.println("list替换前:"+list);//list替换前:[tom, smith, king, milan, tom]
     //list中有tom就替换成汤姆
     Collections.replaceAll(list,"tom","汤姆");
     System.out.println("list替换后:"+list);//list替换后:[汤姆, smith, king, milan, 汤姆]
 }

标签:汇总,元素,list,System,println,add,集合,out
From: https://www.cnblogs.com/nxd-study/p/16797515.html

相关文章

  • Redis数据类型之无序集合
    目录Redis数据类型之无序集合查看命令帮助增加数据查看数据删除数据移动数据返回集合中成员的个数随机返回指定个数的数据判断对象是否存在于集合中随机返回并删除一个成员......
  • 6.MongoDB系列之特殊索引和集合类型
    1.地理空间索引及全文搜索与Elasitcsearch一样,MongoDB同样支持地理空间索引及全文搜索,由于选型常用ES而非MongoDB此处略过2.TTL索引首先先了解下固定集合,其类似于循......
  • 集合—HashSet
    HashSet和ArrayList区别:HashSet无序不可重复,ArrayLIst有序可重复HashSet(无序不重复)1.add方法//以下会去掉重复值hashSet.add(100);hashSet.add(100);System.out.p......
  • LinkedHashSet集合特点
    packagepackage8;importjava.util.LinkedHashSet;/*LinkedHashSet集合特点哈希表和链表实现的Set接口,具有可预测的迭代次序由链表保证元素有序,也就是说元素的存储......
  • 创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
    学生类(需要重写hashCode()和equals())packagepackage7;importjava.util.Objects;publicclassStudent{privateStringname;privateintage;public......
  • 知识点学习掌握-集合
    集合Arraylist与LinkedList的区别​ ArrayList是一个动态数组,但对数据的增加和删除比较复杂,它是基于索引的数据接口,随机访问较为便捷,它的底层是数组,是非同步的。​ Link......
  • 【软件学习】Typora快捷键汇总
    Typora快捷键无序列表:输入-或者*之后输入空格有序列表:输入数字+“.”之后输入空格任务列表:输入-,再空格,再[],在空格,再在]后面空格-有序列表:Ctrl+Shift+[无序......
  • 集合—AyyayList
    集合和数组相比较:数组是定长的,类型是不变的,可以存储基本类型。集合是变长的,类型是可变的,不能存储基本类型。集合的三种接口:通用的父类:CollectionList:ArrayListSet:Has......
  • List集合存储学生对象用三种方式遍历
    packagepackage5;importpackage4.Student;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;//List集合存储学生对象用三种方式遍......
  • List集合相关操作
    packagepackage4;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassListDemo1{publicstaticvoidmain(String[]......