10 集合

1.集合的概念

  • 概念:对象的容器,定义了对多个对象进行操作的常用方法。可以实现数组功能。

  • 和数组的区别:

    1. 数组长度固定,集合长度不固定
    2. 数组可以存储基本类型和引用类型,集合只能存储引用类型
  • 位置:java.util.*

2.Collection接口

2.1Collection体系集合

  • Collection是根接口(父接口)
    • List接口:有序、有下标、元素可重复
    • Set接口:无序、无下标、元素不能重复

image-20220110092546185

2.2Collection父接口

  • 特点:代表一组任意类型的对象,无序、无下标、不能重复----无下标代表不能for循环,但可以foreach
  • 方法:

image-20220110092919691

(1)实例一,以String类型为集合元素

package com.song.demo01;

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

/**
 * Collection接口的使用:
 * (1)添加元素
 * (2)删除元素
 * (3)遍历元素
 * (4)判断
 */
public class demo01 {
    public static void main(String[] args) {
        //创建集合
        Collection collection = new ArrayList();//要new实现类,不能new接口!
        //* (1)添加元素
        collection.add("苹果");
        collection.add("橙子");
        collection.add("西瓜");
        collection.add("草莓");
        collection.add("柚子");
        System.out.println("元素个数:" + collection.size());
        System.out.println("集合元素:" + collection.toString());

        //* (2)删除元素
        collection.remove("草莓");
        System.out.println("删除之后:");
        System.out.println("元素个数:" + collection.size());
        System.out.println("集合元素:" + collection.toString());

        //* (3)遍历元素【重点】
        //3.1方式一:使用增强for
        for (Object object : collection) {
            System.out.println(object);
        }
        //3.2方式二:使用迭代器(专门用来遍历集合的方式)
        Iterator it = collection.iterator();//返回值是一个接口类型
        /*
        Iterator有三个方法:
        1)hasNext();有没有下个元素
        2)next();获取下个元素
        3)remove();删除当前元素
         */
        while (it.hasNext()) {
            String str = (String) it.next();//若已知类型,可以做强转
            System.out.println(str);
            //collection.remove("柚子");//提示:迭代过程中不能使用Collection的方法改变元素
            it.remove();//迭代过程中删除元素的方法
        }
        System.out.println("元素个数:" + collection.size());

        // * (4)判断
        System.out.println("判断是否有西瓜:" + collection.contains("西瓜"));
        System.out.println("判断是否为空:" + collection.isEmpty());
    }
}

(2)实例二:以Student对象为集合元素

package com.song.demo01;

//学生类
public class Student {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.song.demo01;

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

//Collection的使用
public class demo02 {
    public static void main(String[] args) {
        //新建Collection对象
        Collection collection = new ArrayList();
        Student s1 = new Student("zhangsan", 29);
        Student s2 = new Student("lisi", 18);
        Student s3 = new Student("wangwu", 20);
        Student s4 = new Student("lala", 24);
        //1.添加数据
        collection.add(s1);//实际往集合中添加的是堆中对象的地址!
        collection.add(s2);
        collection.add(s3);
        collection.add(s4);
        //collection.add(s3);//可以重复
        System.out.println("元素个数:" + collection.size());
        System.out.println(collection.toString());

        //2.删除
        /*collection.remove(s1);
        //collection.remove(new Student("lisi",18));//不能删除,new出的对象与原有集合中的对象不同
        collection.clear();//清除所有对象,只是将集合中的地址清除了,原有对象仍然在堆中
        System.out.println("元素个数:" + collection.size());
        */


        //3.遍历
        //3.1增强for
        for (Object obj : collection) {
            Student s = (Student) obj;
            System.out.println(s.toString());
        }
        //3.2迭代器:迭代过程中不能出现collection的删除方法
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            Student s = (Student) iterator.next();
            System.out.println(s.toString());
        }

        //4.判断
        System.out.println("集合中是否有元素:" + collection.contains(s2));//true
        System.out.println("集合中是否有元素:" + collection.contains(new Student("lisi", 18)));//false
        System.out.println("集合是否为空:" + collection.isEmpty());

    }
}

2.3List子接口与实现类

2.3.1List接口

  • 特点:有序,由下标,元素可以重复

  • 方法

    image-20220111092529830

  • List接口继承了Collection,因此其包含Collection中的所有方法。

  • List是有序Collection,可以通过下标控制元素位置。

(1)实例一:字符串类型的List

package com.song.demo02;

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

//List的使用
//特点:有序、有下标、元素可重复
public class Demo01 {
    public static void main(String[] args) {
        //创建集合
        List list = new ArrayList();

        //1.添加元素
        list.add("小米");
        list.add("华为");
        list.add(0, "苹果");//指定位置添加
        System.out.println("集合元素个数:" + list.size());
        System.out.println(list.toString());

        //2.删除元素
        /*list.remove("苹果");
        list.remove(0);//指定下标删除
        System.out.println("删除之后集合元素个数:"+list.size());
        System.out.println(list.toString());
        */

        //3.遍历
        //3.1使用for
        System.out.println("-----------3.1使用for--------------");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //3.2使用增强for
        System.out.println("-----------3.2使用增强for--------------");
        for (Object obj : list) {
            System.out.println(obj);
        }
        //3.3使用迭代器
        System.out.println("-----------3.3使用迭代器--------------");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        //3.4使用列表迭代器
        System.out.println("-----------3.4使用列表迭代器--------------");
        //列表迭代器:允许按任意方向(向前、向后)遍历列表、迭代期间修改列表,并获得迭代器在当前列表的位置
        ListIterator listIterator = list.listIterator();
        System.out.println("-------从前往后------");
        while (listIterator.hasNext()) {
            System.out.println("下标:" + listIterator.nextIndex());
            System.out.println(listIterator.next());
        }
        //默认指针是指向第一个元素的,只能从前往后,要想从后往前需要将指针移到最后
        System.out.println("-------从后往前------");
        while (listIterator.hasPrevious()) {
            System.out.println("下标:" + listIterator.previousIndex());
            System.out.println(listIterator.previous());
        }

        //4.判断
        System.out.println("判断元素是否存在:" + list.contains("华为"));
        System.out.println("判断是否为空:" + list.isEmpty());

        //5.获取元素位置
        System.out.println(list.indexOf("华为"));

    }
}

(2)实例二:数字类型的List

package com.song.demo02;

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

//List的使用
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        List list = new ArrayList();
        //1.添加数字数据,隐含自动装箱操作
        //集合中不能添加基本类型,基本类型需要自动装箱成包装类
        list.add(20);
        list.add(10);
        list.add(24);
        list.add(26);
        System.out.println("元素个数:" + list.size());
        System.out.println(list.toString());

        //2.删除数字
        /*list.remove(0);//数值类型的集合,根据下标删除
        list.remove((Object) 10);//若要根据数值删除,转成Object对象或者Integer对象
        list.remove(new Integer(26));
        System.out.println("元素个数:" + list.size());
        System.out.println(list.toString());
         */

        //3.补充方法subList();返回子集合
        List sublist = list.subList(1, 3);//从1开始到3前,左闭右开
        System.out.println("元素个数:" + sublist.size());
        System.out.println(sublist.toString());


    }

}

2.3.2List实现类

  • ArrayList【重点】

    • 数组结构,查询快、增删慢;
    • JDK1.2版本,运行效率快、线程不安全。
  • Vector

    • 数组结构,查询快、增删慢;
    • JDK1.0版本,运行效率快、线程安全
  • LinkdedList

    • 链表结构,增删快、查询慢
(1)ArrayList

源码分析:

  • DEFALUT_CAPACITY=10; 默认容量 --向集合添加元素后,默认容量为10

    • 注意:如果没有向集合中添加任何元素是,集合容量为0
    • 向集合添加任意一个元素后,集合容量变为10
    • 添加第11个元素时,集合容量变为15
    • 每次扩容,是原来的1.5倍
  • elementData; 存放元素的数组

  • size 实际元素个数

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    //初始创建时,均为空,条件成立,返回的是默认容量10
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

//核心部分:数组扩容的代码  
//初始minCapacity=10
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//0
        int newCapacity = oldCapacity + (oldCapacity >> 1);//右移一位,相当于除以2
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;//10
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//即当添加任意一个元素后,初始容量变为10
    }

实例:

提示:若想根据对象值进行删除、查找等,需要重写equals()方法,因为equals()方法默认比较的是对象地址,而非对象中的属性值。

package com.song.demo02;

import java.util.Objects;

//学生类
public class Student {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

    @Override
    public boolean equals(Object obj) {
        //1.判断是不是同一个对象
        if (this == obj) {
            return true;
        }
        //2.判断是否为空
        if (obj == null) {
            return false;
        }
        //3.判断是否是Student类型
        if (obj instanceof Student) {
            Student stu = (Student) obj;
            //4.相同类型则比较属性
            if (this.name.equals(stu.getName()) && this.age == stu.getAge()) {//字符串的比较不能用==,要用equals
                return true;
            }
        }
        //5.不满足条件返回false
        return false;
    }

}
package com.song.demo02;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

//ArrayList的使用
//存储结构:数组-->查找遍历速度快,增删慢
public class Demo03 {
    public static void main(String[] args) {
        //创建集合
        /**size=0 初始创建,容量为0;
         * 向集合中添加任意一个元素后,容量变为10
         * 后续添加的元素超过10,添加第11个元素时会继续扩容,容量变为15
         * 每次扩容,都是原来的1.5倍
         */
        ArrayList arrayList = new ArrayList<>();
        //1.添加元素
        Student s1 = new Student("zhangsan", 20);
        Student s2 = new Student("lisi", 22);
        Student s3 = new Student("wangwu", 18);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s2);
        System.out.println("元素个数:" + arrayList.size());
        System.out.println(arrayList.toString());

        //2.删除元素
        /*arrayList.remove(s1);
        arrayList.remove(new Student("wangwu", 18));//正常情况下不能删除,是一个新的对象,实际集合中存储的是对象的地址
        //删除过程中会调用到的equals(this==obj)方法,比较的是地址;如果要比较值,则需要重写equals()方法
        //重写equals方法后,可以删除
        System.out.println("删除之后元素个数:" + arrayList.size());
        System.out.println(arrayList.toString());
        */

        //3.遍历元素【重点】
        //3.1增强for
        //3.2使用for
        //3.3迭代器
        Iterator it = arrayList.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.toString());
        }
        //3.4使用列表迭代器
        System.out.println("------------从前往后------");
        ListIterator lit = arrayList.listIterator();
        while (lit.hasNext()) {
            Student s = (Student) lit.next();
            System.out.println(s.toString());
        }
        System.out.println("------------从后往前------");
        while (lit.hasPrevious()) {
            Student s = (Student) lit.previous();
            System.out.println(s.toString());
        }

        //4.判断
        System.out.println("元素是否存在:" + arrayList.contains(new Student("wangwu", 18)));//equals重写后可以根据对象值判断是否存在
        System.out.println("集合是否为空:" + arrayList.isEmpty());

        //5.查找元素位置
        System.out.println(arrayList.indexOf(new Student("wangwu", 18)));//equals重写后可以根据对象值查找位置
    }
}

(2)Vector
  • 数组结构,查询快、增删慢;
  • JDK1.0版本,运行效率快、线程安全

Vector类可以实现可增长的对象数组,与数组一样,它包含可以使用整数索引进行访问的组件。但是Vector的大小可以根据需要增大或缩小,以适应创建Vector后进行添加或者移除项的操作。

实例:

package com.song.demo02;

import java.util.Enumeration;
import java.util.Vector;

//Vector的使用
//存储结构:数组
public class Demo04 {
    public static void main(String[] args) {
        //创建集合
        Vector vector = new Vector<>();
        //1.添加元素
        vector.add("草莓");
        vector.add("芒果");
        vector.add("西瓜");
        System.out.println("元素个数:" + vector.size());
        System.out.println(vector.toString());
        //2.删除
        /*vector.remove(0);//根据下标删除
        vector.remove("芒果");
        vector.clear();//清空
        System.out.println("元素个数:" + vector.size());
        System.out.println(vector.toString());

         */
        //3.遍历
        //3.1for
        //3.2增强for
        //3.3迭代器
        //3.4枚举器
        Enumeration en = vector.elements();
        while (en.hasMoreElements()) {
            String o = (String) en.nextElement();
            System.out.println(o);
        }

        //4.判断
        System.out.println("判断是否包含元素:" + vector.contains("西瓜"));
        System.out.println("判断是否为空:" + vector.isEmpty());

        //其他方法
        System.out.println("第一个位置的元素" + vector.firstElement());
        System.out.println("最后一个位置的元素" + vector.lastElement());
        System.out.println("获取指定位置的元素" + vector.elementAt(1));

    }
}
(3)LinkedList

链表结构(双向链表),增删快、查询慢

源码分析:

  • 三个属性:

    • 初始:first=null,last=null,size=0
  • 每个节点Node

    • item:实际数据
    • next:下一个节点
    • prev:前一个节点
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++;
    }

实例:

package com.song.demo02;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

//LinkedList的使用
//存储结构:双向链表
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        LinkedList list = new LinkedList<>();
        //1.添加元素
        Student s1 = new Student("张三", 21);
        Student s2 = new Student("李四", 24);
        Student s3 = new Student("王五", 20);
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s2);//可以重复
        System.out.println("元素个数:" + list.size());
        System.out.println(list.toString());

        //2.删除
        /*list.remove(0);//根据下标删除
        list.remove(new Student("李四", 24));//重写equals()方法后,可以根据对象值删除
        list.clear();//清空
        System.out.println("删除之后元素个数:" + list.size());
        System.out.println(list.toString());

         */

        //3.遍历
        //3.1for遍历
        System.out.println("-----------------for遍历-----------------");
        for (int i = 0; i < list.size(); i++) {
            Student stu = (Student) list.get(i);
            System.out.println(stu.toString());
        }
        //3.2增强for
        System.out.println("-----------------增强for-----------------");
        for (Object obj : list) {
            Student stu = (Student) obj;
            System.out.println(stu.toString());
        }
        //3.3迭代器Iterator
        System.out.println("-----------------迭代器Iterator-----------------");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Student stu = (Student) it.next();
            System.out.println(stu.toString());
        }
        //3.4列表迭代器ListIterator
        System.out.println("-----------------列表迭代器ListIterator-----------------");
        ListIterator lit = list.listIterator();
        while (lit.hasNext()) {
            Student stu = (Student) lit.next();
            System.out.println(stu.toString());
        }

        //4.判断
        System.out.println("判断元素是否存在" + list.contains(s1));
        System.out.println("判断是否为空" + list.isEmpty());
        //5.获取
        System.out.println(list.indexOf(s2));//获取元素位置

    }
}
(4)不同结构的实现方式
  • ArrayList:数组结构
    • 必须开辟连续的空间
    • 查询快,增删慢
  • LinkedList:双向链表
    • 无需开辟连续的空间
    • 查询慢,增删快

image-20220112100130601

2.4泛型和工具类

  • Java泛型是JKD1.5中引入的新特性,其本质是参数化类型,把类型作为参数传递

  • 常见形式有:

    • 泛型类、
    • 泛型接口、
    • 泛型方法。
  • 语法:

    • <T,…>T称为类型占位符,表示一种引用类型
  • 好处:

    • 提高代码的重用性—一个方法可以传递任何类型的数据
    • 防止类型转换异常,提高代码的安全性

2.4.1泛型类

package com.song.demo03;

public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类创建对象---
        /* 注意:
        1)T只能是引用类型
        2)不同的泛型对象之间不能相互复制
         */
        //String类型
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        myGeneric.t = "hello";
        myGeneric.show("大家好!");
        String str = myGeneric.getT();
        System.out.println(str);

        //Integer
        MyGeneric<Integer> myGeneric1 = new MyGeneric<>();
        myGeneric1.t = 108;
        myGeneric1.show(200);
        Integer integer = myGeneric1.getT();
        System.out.println(integer);


    }
}

2.4.2泛型接口

接口:

package com.song.demo03;
//泛型接口
//语法:接口名<T>
//注意:不能使用泛型创建静态常量
public interface MyInterface<T> {
    String name="张三";

    T server(T t);
}

实现类一(实现接口时确定类型):

package com.song.demo03;

//接口的实现类,指明了泛型的类型
public class MyInterfaceImpl implements MyInterface<String> {
    @Override
    public String server(String s) {
        System.out.println(s);
        return s;
    }
}

实现类二(实现接口时不确定类型):

package com.song.demo03;

//实现类实现接口时不确定类型,实现类的泛型就是接口的泛型
public class MyInterfaceImpl2<T> implements MyInterface<T> {
    @Override
    public T server(T t) {
        System.out.println(t);
        return t;
    }
}

测试:

package com.song.demo03;

public class TestGeneric {
    public static void main(String[] args) {
        //泛型接口的两种实现方式
        //1.实现类中指定类型
        MyInterfaceImpl myInterface = new MyInterfaceImpl();
        myInterface.server("songsong");

        //2.把实现类变为泛型类,实例化时指定类型
        MyInterfaceImpl2<Integer> myInterfaceImpl2 = new MyInterfaceImpl2<Integer>();
        myInterfaceImpl2.server(1000);


    }
}

2.4.3泛型方法

package com.song.demo03;

//泛型方法
//语法:<T> 返回值类型 方法名(){}
public class MyGenericMethod {
    //泛型方法,该T只能在此方法中使用
    public <T> void show(T t) {
        T t2;//可以创建变量,但不能实例化(new)
        t2 = t;
        System.out.println("泛型方法:" + t);
    }

}
package com.song.demo03;

public class TestGeneric {
    public static void main(String[] args) {
        //泛型方法
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        myGenericMethod.show("中国加油");//不需要指明类型,直接传递想要的参数,根据参数类型决定
        myGenericMethod.show(200);
        myGenericMethod.show(3.1415926);

    }
}

2.4.4泛型集合

  • 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
  • 特点:
    • 编译时即可检查,而非运行时抛出异常
    • 访问时,不必类型转换(拆箱)
    • 不同泛型之间不能相互赋值,泛型不存在多态。
package com.song.demo03;

import com.song.demo02.Student;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath;

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

public class Demo01 {
    public static void main(String[] args) {
        /*ArrayList arrayList=new ArrayList<>();
        arrayList.add("wangwu");
        arrayList.add("zhangsan");
        arrayList.add(0);
        arrayList.add(20);

        for (Object obj:arrayList             ) {
            System.out.println(obj);//没问题
            String str=(String)obj;
            //System.out.println(str);//有问题,类型转换异常
        }*

         */

        //使用泛型集合可以避免类型转换异常
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("wangwu");
        arrayList.add("zhangsan");
        //arrayList.add(20);//直接不能添加,报错,避免后面再出问题

        for (String str : arrayList) {
            System.out.println(str);
        }

        ArrayList<Student> arrayList1 = new ArrayList<Student>();
        Student s1 = new Student("张三", 21);
        Student s2 = new Student("李四", 24);
        Student s3 = new Student("王五", 20);
        arrayList1.add(s1);
        arrayList1.add(s2);
        arrayList1.add(s3);
        //arrayList1.add("zhangsan");//直接不能添加,报错,避免后面再出问题
        Iterator<Student> it = arrayList1.iterator();
        while (it.hasNext()) {
            Student stu = it.next();//少了一步强制类型转换
            System.out.println(stu.toString());
        }
    }
}

2.5Set子接口与实现类

  • 特点:无序、无下标、元素不可重复。

  • 方法:全部继承自Collection类

  • 可以将set理解为不包含重复对象的collection

2.5.1Set 接口

package com.song.demo04;

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

//测试Set接口

/**
 * 特点:
 * (1)无序,没有下标
 * (2)不能重复
 */

public class Demo01 {
    public static void main(String[] args) {
        //创建集合
        Set<String> set = new HashSet<String>();
        //1.添加数据
        set.add("苹果");
        set.add("小米");
        set.add("华为");
        set.add("Oppo");
        //set.add("华为");
        System.out.println("元素个数:" + set.size());
        System.out.println(set.toString());//无序--->打印顺序与添加顺序可能不一致
        //2.删除
        /*set.remove("小米");//无下标,不能通过下标删除
        //set.clear();//清空
        System.out.println("元素个数:" + set.size());
        System.out.println(set.toString());

         */
        //3.遍历【重点】
        //3.1增强for
        System.out.println("------------增强for----------");
        for (String str : set) {
            System.out.println(str);
        }

        //3.2迭代器
        System.out.println("------------迭代器----------");
        Iterator it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        //4.判断
        System.out.println("是否包含元素:" + set.contains("小米"));
        System.out.println("集合是否为空:" + set.isEmpty());

    }
}

2.5.2Set实现类

  • HashSet【重点】

    • 存储结构:Hash表

    • 基于HashCode计算元素存放位置

    • 当存入元素的哈希码相同时,会调用equals()进行确认,如果认为值true,则拒绝后者存入。

  • TreeSet

    • 存储结构:红黑树
    • 基于排列顺序实现元素不重复
    • 实现了SortedSet接口,对集合元素自动排序
    • 元素对象的类型必须实现Comparable接口,指定排序规则。
    • 通过CompareTo方法确定是否为重复元素。
(1)HashSet

存储过程:

  1. 根据hashCode计算保存的位置(数组),如果位置为空,则直接保存,如果不为空则执行第二步
  2. 再执行equals方法,如果equals方法位true,则认为是重复,否则形成链表

既有数组又有链表

image-20220113093327010

实例一:

package com.song.demo04;

import java.util.HashSet;
import java.util.Iterator;

//HashSet的使用
//存储结构:哈希表(数组+链表+红黑树)
public class Demo02 {
    public static void main(String[] args) {
        //新建集合
        HashSet<String> hashSet = new HashSet<String>();
        //1.添加元素
        hashSet.add("张三");
        hashSet.add("李四");
        hashSet.add("王五");
        hashSet.add("宋六");
        System.out.println("元素个数:" + hashSet.size());
        System.out.println(hashSet.toString());

        //2.删除元素
        /*hashSet.remove("王五");
        hashSet.clear();//清空
        System.out.println("删除后元素个数:" + hashSet.size());
        System.out.println(hashSet.toString());
         */

        //3.遍历
        //3.1增强for
        System.out.println("-------------------增强for------------");
        for (String str : hashSet) {
            System.out.println(str);
        }
        //3.2迭代器
        System.out.println("-------------------迭代器------------");
        Iterator it = hashSet.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        //4.判断
        System.out.println("判断元素是否存在:" + hashSet.contains("李四"));
        System.out.println("判断集合是否为空:" + hashSet.isEmpty());
        
    }
}

实例二:

package com.song.demo04;

import java.util.Objects;

public class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

    /*@Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        if (o instanceof Person) {
            Person person = (Person) o;
            if (age == person.age && name.equals(person.getName()))
                return true;
        }
        return false;

    }

    @Override
    public int hashCode() {
        //根据名字、年龄来计算hashCode,可以让相同值的的hashCode一致(既数组的同一位置)
        int n1 = this.name.hashCode();
        int n2 = this.age;//可以直接用年龄的数字,也可以对其做一定的加减等操作
        //int n2 = this.age+31;//
        //1)31是一个质数,减少散列冲突;2)31提高执行效率
        return n1 + n2;
    }

     */
    //Alt+Insert 中有快速重写equals和hashCode的方法


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

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

import java.util.HashSet;
import java.util.Iterator;

//HashSet的使用
//存储结构:哈希表(数组+链表+红黑树)

/**
 * 存储过程:
 * (1)根据hashCode计算保存的位置(数组),如果位置为空,则直接保存,如果不为空则执行第二步
 * (2)再执行equals方法,如果equals方法位true,则认为是重复,否则形成链表
 * (3)
 */
public class Demo03 {
    public static void main(String[] args) {
        //创建集合
        HashSet<Person> person = new HashSet<>();
        //1.添加元素
        Person p1 = new Person("张三", 18);
        Person p2 = new Person("李四", 26);
        Person p3 = new Person("王五", 28);
        Person p4 = new Person("宋六", 20);
        person.add(p1);
        person.add(p2);
        person.add(p3);
        person.add(p4);
        //person.add(p4);//重复,不能再添加
        person.add(new Person("宋六", 20));//可以添加,new了一个新的对象,地址不同,计算出的hashCode不同,可以直接存储
        /**想根据值判断,则:
         * 1)首先需重写hashCode()方法,让值相同的计算出的hashCode一样(数组的相同位置)---此时用equals判断地址,会形成链表
         * 2)再重写equals方法,根据值判断是否一致,而非根据地址判断
         */
        System.out.println("元素个数:" + person.size());
        System.out.println(person.toString());

        //2.删除元素
        person.remove(p1);
        person.remove(new Person("宋六", 20));//重写hashCode和equals后可以删除
        System.out.println("删除之后元素个数:" + person.size());
        System.out.println(person.toString());

        //3.遍历元素
        //3.1增强for
        for (Person p : person) {
            System.out.println(p.toString());
        }
        System.out.println("-------------");
        //3.2迭代器
        Iterator it = person.iterator();
        while (it.hasNext()) {
            System.out.println(it.next().toString());
        }

        //4.判断
        System.out.println("元素是否存在" + person.contains(p2));
        System.out.println("元素是否存在" + person.contains(new Person("李四", 26)));//重写hashCode和equals后可以根据值判断
        System.out.println("集合是否为空" + person.isEmpty());


    }
}
(2)TreeSet
  • 存储结构:红黑树
  • 基于排列顺序实现元素不重复
  • 实现了SortedSet接口,对集合元素自动排序
  • 元素对象的类型必须实现Comparable接口,指定排序规则。
  • 通过CompareTo方法确定是否为重复元素。

红黑树是一个二叉查找树(每个节点最多只有2个子节点,且左节点小于右节点,涉及到比较)+颜色(保证左右平衡)

image-20220113100616519

实例一:

package com.song.demo04;
//TreeSet的使用
//存储结构:红黑树

import java.util.Iterator;
import java.util.TreeSet;

public class Demo04 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<String> treeset = new TreeSet<>();
        //1.添加元素
        treeset.add("xyz");
        treeset.add("abc");
        treeset.add("hello");
        treeset.add("song");
        treeset.add("xyz");//重复,未添加
        System.out.println("元素个数:" + treeset.size());
        System.out.println(treeset.toString());//打印出的是按照字母表顺序排列的

        //2.删除
        treeset.remove("xyz");
        System.out.println("元素个数:" + treeset.size());
        System.out.println(treeset.toString());

        //3.遍历
        //3.1增强for
        for (String str : treeset) {
            System.out.println(str);
        }
        System.out.println("-------------------------");
        //3.2迭代器
        Iterator it = treeset.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        //4.判断
        System.out.println("元素是否存在:" + treeset.contains("abc"));
        System.out.println("集合是否为空:" + treeset.isEmpty());


    }
}

实例二:

package com.song.demo04;

import java.util.Iterator;
import java.util.TreeSet;

//TreeSet的使用
//存储结构:红黑树

/**
 * 要求:元素必须实现Comparable接口,compareTo()方法返回值为0,被认为是重复元素
 */

public class Demo05 {
    public static void main(String[] args) {
        //1.创建集合
        TreeSet<Person> person = new TreeSet<>();
        //1.添加元素
        Person p1 = new Person("zhangsan", 18);
        Person p2 = new Person("lisi", 26);
        Person p3 = new Person("wangwu", 28);
        Person p4 = new Person("lisi", 20);
        //直接添加不成功,不知道如何把比较(二叉查找树要求左节点<右节点)
        //需要实现Comparable接口,重写compareTo方法,告知比较规则
        person.add(p1);
        person.add(p2);
        person.add(p3);
        person.add(p4);
        System.out.println("元素个数:" + person.size());
        System.out.println(person.toString());//按照排序输出,先姓名后年龄,可自定义

        //2.删除
        /*person.remove(p1);
        person.remove(new Person("lisi", 20));//实现Comparable接口之后,比较值,可以删除
        System.out.println("删除之后元素个数:" + person.size());
        System.out.println(person.toString());//按照排序输出,先姓名后年龄,可自定义
*/
        //3.遍历
        //3.1使用增强for
        for (Person p : person) {
            System.out.println(p.toString());
        }
        System.out.println("---------------------");
        //3.2使用迭代器
        Iterator it = person.iterator();
        while (it.hasNext()) {
            System.out.println(it.next().toString());
        }

        //4.判断
        System.out.println(person.contains(p2));
        System.out.println(person.contains(new Person("lisi", 20)));//可以判断

    }
}

实例三:

package com.song.demo04;

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

//TreeSet集合的使用
//Comparator接口:实现定制比较(比较器)
//Comparable:可比较的
public class Demo06 {
    public static void main(String[] args) {
        //创建集合,并指定比较规则
        TreeSet<Person> person = new TreeSet<>(new Comparator<Person>() {//采用匿名内部类的方式
            @Override
            public int compare(Person o1, Person o2) {//拿两个对象定制比较规则
                int n1 = o1.getAge() - o2.getAge();
                int n2 = o1.getName().compareTo(o2.getName());
                return n1 == 0 ? n2 : n1;//先比较年龄再比较性别
            }
        });
        //1.添加元素
        Person p1 = new Person("zhangsan", 18);
        Person p2 = new Person("lisi", 26);
        Person p3 = new Person("wangwu", 28);
        Person p4 = new Person("lisi", 20);
        person.add(p1);
        person.add(p2);
        person.add(p3);
        person.add(p4);
        System.out.println("元素个数:" + person.size());
        System.out.println(person.toString());//按照排序输出,先姓名后年龄,可自定义


    }
}

实例四:

package com.song.demo04;

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

//要求:使用TreeSet集合实现字符串按照长度进行排序(最短的在前面,长度一样再根据字母顺序比较)
//使用Comparatar接口定制比较
public class Demo07 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1 = o1.length() - o2.length();
                int n2 = o1.compareTo(o2);
                return n1 == 0 ? n2 : n1;
            }
        });
        //1.添加元素
        treeSet.add("hello world");
        treeSet.add("abc");
        treeSet.add("xyz");
        treeSet.add("Beijing");
        treeSet.add("zhangsang");
        treeSet.add("lisi");
        System.out.println(treeSet.size());
        System.out.println(treeSet.toString());

    }
}

3.Map接口与实现类

3.1Map集合体系结构

  • Map集合主要用于存储键值对
  • 键不允许重复(唯一),无序,无下标,不允许重复
  • 值允许重复,无序,无下标

image-20220113172300854

3.2Map父接口

  • 特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可以重复。
  • 方法:

image-20220113173258935

image-20220114092932924

  • entrySet()方法的效率要高于keySet()

使用实例:

package com.song.demo05;
//Map接口的使用

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

/**
 * 特点:
 * (1)存储键值对
 * (2)键不能重复
 * (3)无序
 */
public class Demo01 {
    public static void main(String[] args) {
        //创建Map集合,需要指定Key和Value的类型
        Map<String, String> map = new HashMap<>();
        //1.添加元素
        map.put("cn", "中国");
        map.put("uk", "英国");
        map.put("usa", "美国");
        map.put("cn", "中华人民共和国");//key相同的,后面添加的value会把前面的覆盖掉
        System.out.println("元素个数:" + map.size());
        System.out.println(map.toString());

        //2.删除元素
        /*map.remove("usa");//通过键key来删除
        System.out.println("元素个数:"+map.size());
        System.out.println(map.toString());

         */

        //3.遍历【遍历】
        //3.1使用keySet(),得到的返回值是所有key的Set集合
        System.out.println("----------------------keySet------------------");
        //Set<String> keyset = map.keySet();//Set的类型就是key的类型
        //for (String key : keyset) {
        for (String key : map.keySet()) {
            System.out.println(key + "------->" + map.get(key));//遍历的是所有key,再以此得到value
        }
        //3.2使用entrySet(),得到的返回值是由key,value组成的entry,构成的Set集合
        System.out.println("----------------------entrySet------------------");
        Set<Map.Entry<String, String>> entryset = map.entrySet();//接口Map.Entry要指明key和value的类型
        for (Map.Entry<String, String> entry : entryset) {
            System.out.println(entry.getKey() + "---------->" + entry.getValue());
        }

        //4.判断
        System.out.println("key是否存在" + map.containsKey("cn"));
        System.out.println("value是否存在" + map.containsValue("俄罗斯"));

    }
}

3.3Map接口的实现类

  • HashMap【重点】

    • JDK1.2版本,线程不安全(只能单线程下使用),运行效率快;允许用null作为key或者value。
  • HashTable

    • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或者value
  • Properties:

    • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
  • TreeMap

    • 实现了SortedMap接口(是Map的子接口),可以对key自动排序

3.3.1HadhMap

  • HashMap【重点】
    • JDK1.2版本,线程不安全(只能单线程下使用),运行效率快;允许用null作为key或者value。
    • MapHash的初始默认容量是16,默认加载因子0.75(容量16,用到16*0.75=12时开始扩容),后续的每次扩容会扩大2倍,如16->32
    • 当数组数组长度大于64且某处位置的链表长度大于8,则把链表调整为红黑树(树的查找遍历更快)
    • 当链表(树?)长度小于6时,把红黑树调整回链表。
(1)源码分析
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //HashMap的初始容量大小 2的4次方
static final int MAXIMUM_CAPACITY = 1 << 30;//HashMap的数组最大容量 2的30次方
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
static final int TREEIFY_THRESHOLD = 8;//jdk1.8 当链表长度大于8时,调整为红黑树
static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度小于6时,调整回链表
static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整为红黑树

transient Node<K,V>[] table;//数组
size;//元素个数

//刚创建HashMap后,还未添加任何元素时,table=null,size=0
//添加第一个元素时,容量才变为16------
//目的:为了节省空间

image-20220114143250364

构造方法:

public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

put方法:

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
}

总结:

  1. HashMap刚创建时,table是null,是为了节省空间,当添加第一个元素时,table容量调整为16
  2. 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩后大小变为原来的2倍,目的是减少调整元素的个数。
  3. jdk1.8 当每个链表长度大于8,并且元素个数大于等于64时,会调整为红黑树,目的是提高执行效率
  4. jdk1.8 当链表长度小于6时,调整为链表
  5. jdk1.8以前,链表时是插入,jdk1.8以后链表是尾插入

HashSet与HashMap的区别:

HashSet里面本质用的就是HashMap

public HashSet() {
        map = new HashMap<>();
    }
(2)使用实例
package com.song.demo05;

import java.util.Objects;

public class Student {
    private String name;
    private int stuNo;

    public Student() {
    }

    public Student(String name, int stuNo) {
        this.name = name;
        this.stuNo = stuNo;
    }

    public String getName() {
        return name;
    }

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

    public int getStuNo() {
        return stuNo;
    }

    public void setStuNo(int stuNo) {
        this.stuNo = stuNo;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return stuNo == student.stuNo && Objects.equals(name, student.name);
    }

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

package com.song.demo05;


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

/**
 * HashMap的使用:
 * 存储结构:哈希表(数组+链表+红黑树)
 * <p>
 * 元素增加时重复的判断依据:
 * 使用key的hashcode和equals作为重复依据(默认用得是地址比较)
 * 要想根据值比较,需要重写hashcode和equals
 */
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        HashMap<Student, String> hashmap = new HashMap<Student, String>();

        //1.增加元素
        Student s1 = new Student("张三", 213);
        Student s2 = new Student("李四", 104);
        Student s3 = new Student("王五", 890);
        Student s4 = new Student("六六", 432);
        hashmap.put(s1, "北京");
        hashmap.put(s2, "上海");
        hashmap.put(s3, "南京");
        hashmap.put(s4, "青岛");
        //hashmap.put(s4, "大同");//不允许key重复,不能添加新的键值对,只会覆盖原来的value
        hashmap.put(new Student("李四", 104), "杭州");//可以添加新的键值对,比较的是地址,认为key不同,故新增
        //当重写hashcode和equals 方法后,比较的是值认为key重复,不能新增键值对,会覆盖原来的value
        System.out.println("元素个数:" + hashmap.size());
        System.out.println(hashmap.toString());

        //2.删除元素
        hashmap.remove(s1);
        System.out.println("删除之后元素个数:" + hashmap.size());
        System.out.println(hashmap.toString());

        //3.遍历
        //3.1使用keySet
        for (Student stu : hashmap.keySet()) {
            System.out.println(stu.toString() + "----->" + hashmap.get(stu));
        }
        System.out.println("------------------------");
        //3.2使用entrySet
        for (Map.Entry<Student, String> entry : hashmap.entrySet()) {
            System.out.println(entry.getKey() + "------" + entry.getValue());
        }

        //4.判断
        System.out.println("Key是否存在:" + hashmap.containsKey(s2));
        System.out.println("value是否存在:" + hashmap.containsValue("杭州"));
    }
}

3.3.2HashTable

  • HashTable—几乎不使用了

    • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或者value
    • 默认初始容量11,默认加载因子0.75
  • Properties:-----与流的关系紧密,在流章节详细讲

    • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。

3.3.3TreeMap

  • TreeMap
    • 实现了SortedMap接口(是Map的子接口),可以对key自动排序

TreeSet与TreeMap的区别:

TreeSet本质就是通过TreeMap实现的。

public TreeSet() {
        this(new TreeMap<E,Object>());
    }

使用实例:

package com.song.demo05;

import java.util.Objects;

public class Student implements Comparable<Student> {

    private String name;
    private int stuNo;

    public Student() {
    }

    public Student(String name, int stuNo) {
        this.name = name;
        this.stuNo = stuNo;
    }

    public String getName() {
        return name;
    }

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

    public int getStuNo() {
        return stuNo;
    }

    public void setStuNo(int stuNo) {
        this.stuNo = stuNo;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return stuNo == student.stuNo && Objects.equals(name, student.name);
    }

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

    @Override
    public int compareTo(Student o) {
        int n2 = this.stuNo - o.stuNo;
        return n2;//直接比较学号
    }
}

1)实现Comparable接口实现比较

package com.song.demo05;

import java.util.Map;
import java.util.TreeMap;

/**
 * TreeMap的使用
 * 存储结构:红黑树(左节点<右节点)
 * 两种比较方式:
 * 1)实现Comparable接口
 * 2)定制比较Comparator
 */
public class Demo03 {
    public static void main(String[] args) {
        //新建集合
        TreeMap<Student, String> treemap = new TreeMap<>();
        //1.增加元素
        Student s1 = new Student("张三", 213);
        Student s2 = new Student("李四", 104);
        Student s3 = new Student("王五", 890);
        Student s4 = new Student("六六", 432);
        treemap.put(s1, "北京");
        treemap.put(s2, "上海");
        treemap.put(s3, "南京");
        treemap.put(s4, "青岛");
        //直接添加出现类型转换异常,不能Comparable,不能比较左右节点
        //要求Student实现一个Comparable接口,指定比较规则,实现可比较,才能添加
        treemap.put(new Student("六六", 432), "深圳");//不能添加,实现Comparable接口后制定了按照学号比较,此时学号一样,则认为key重复,故value会覆盖原来的值
        System.out.println("元素个数:" + treemap.size());
        System.out.println(treemap.toString());

        //2.删除
        treemap.remove(s3);
        treemap.remove(new Student("六六", 432));//按照学号比较,可以删除
        System.out.println("元素个数:" + treemap.size());
        System.out.println(treemap.toString());

        //3.遍历
        //3.1使用keySet
        for (Student stu : treemap.keySet()) {
            System.out.println(stu.toString() + "----" + treemap.get(stu));
        }
        System.out.println("----------------------------------");
        //3.2使用entrySet
        for (Map.Entry<Student, String> entry : treemap.entrySet()) {
            System.out.println(entry.getKey() + "-----" + entry.getKey());
        }

        //4.判断
        System.out.println(treemap.containsKey(s2));
        System.out.println(treemap.containsValue(213));


    }
}

2)通过Comparator实现定制比较

        //新建集合
        TreeMap<Student, String> treemap = new TreeMap<Student, String>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n1 = o1.getStuNo() - o2.getStuNo();
                return n1;//只根据学号比较
            }
        });

4.Collections工具类

  • 概念:集合工具类,定义除了存取以外的集合常用方法。
  • (相比Collection,多了一个s)
  • 方法:

image-20220114154513708

实例:

package com.song.demo05;

import java.util.*;

/**
 * Collection工具类的使用
 */
public class Demo05 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(25);
        list.add(39);
        list.add(11);
        list.add(22);
        list.add(40);
        list.add(18);
        System.out.println("排序之前" + list.toString());
        //sort排序方法
        Collections.sort(list);//从小到大
        System.out.println("排序之后" + list.toString());

        //binarySearch二分查找
        int i = Collections.binarySearch(list, 39);//返回值是int类型,能找到则返回位置,未找到则返回值小于0
        System.out.println(i);

        //copy复制
        List<Integer> dest = new ArrayList<>();
        //Collections.copy(dest, list);//直接copy有问题,要求dest的大小与list相同
        for (int i1 = 0; i1 < list.size(); i1++) {
            dest.add(0);
        }
        Collections.copy(dest, list);//可以先给dest赋值0,使两个列表size一致,再赋值
        System.out.println(dest.toString());

        //reverse反转
        Collections.reverse(list);
        System.out.println(list.toString());

        //shuffle打乱
        Collections.shuffle(list);
        System.out.println(list.toString());

        //补充:list转成数组
        System.out.println("list转成数组");
        Integer[] array = list.toArray(new Integer[0]);//返回值是数组;构造时new的Interger长度无所谓,只是为了指明一种类型
        System.out.println(array.length);
        System.out.println(Arrays.toString(array));

        //补充:数组转成集合
        System.out.println("数组转成集合");
        String[] name = {"张三", "李四", "王五", "刘六"};
        List<String> list2 = Arrays.asList(name);
        //数组转出来的集合是受限集合,不能添加和删除元素,不能add和remove
        System.out.println(list2.size());
        System.out.println(list2.toString());

        //把基本类型的数组转成集合是,需要修改为包装类型(引用类型)
        Integer[] nums = {12, 4, 2, 1, 44, 456, 34};
        List<Integer> list3 = Arrays.asList(nums);
        System.out.println(list3.size());

    }
}

总结:

  • 集合的概念:

    • 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法
  • List集合:

    • 有序、有下标、元素可以重复(ArrayList、LinkedList、Vector)
  • Set集合:

    • 无序、无下标、元素不可重复(HashSet、TreeSet)
  • Map集合:

    • 存储一对数据,无序、无下标,键不可重复,值可以重复(HashMap、HashTable、TreeMap)
  • Collections:
    list.add(25);
    list.add(39);
    list.add(11);
    list.add(22);
    list.add(40);
    list.add(18);
    System.out.println(“排序之前” + list.toString());
    //sort排序方法
    Collections.sort(list);//从小到大
    System.out.println(“排序之后” + list.toString());

      //binarySearch二分查找
      int i = Collections.binarySearch(list, 39);//返回值是int类型,能找到则返回位置,未找到则返回值小于0
      System.out.println(i);
    
      //copy复制
      List<Integer> dest = new ArrayList<>();
      //Collections.copy(dest, list);//直接copy有问题,要求dest的大小与list相同
      for (int i1 = 0; i1 < list.size(); i1++) {
          dest.add(0);
      }
      Collections.copy(dest, list);//可以先给dest赋值0,使两个列表size一致,再赋值
      System.out.println(dest.toString());
    
      //reverse反转
      Collections.reverse(list);
      System.out.println(list.toString());
    
      //shuffle打乱
      Collections.shuffle(list);
      System.out.println(list.toString());
    
      //补充:list转成数组
      System.out.println("list转成数组");
      Integer[] array = list.toArray(new Integer[0]);//返回值是数组;构造时new的Interger长度无所谓,只是为了指明一种类型
      System.out.println(array.length);
      System.out.println(Arrays.toString(array));
    
      //补充:数组转成集合
      System.out.println("数组转成集合");
      String[] name = {"张三", "李四", "王五", "刘六"};
      List<String> list2 = Arrays.asList(name);
      //数组转出来的集合是受限集合,不能添加和删除元素,不能add和remove
      System.out.println(list2.size());
      System.out.println(list2.toString());
    
      //把基本类型的数组转成集合是,需要修改为包装类型(引用类型)
      Integer[] nums = {12, 4, 2, 1, 44, 456, 34};
      List<Integer> list3 = Arrays.asList(nums);
      System.out.println(list3.size());
    

    }
    }


# 总结:

- 集合的概念:
  - 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法

- List集合:
  - 有序、有下标、元素可以重复(ArrayList、LinkedList、Vector)

- Set集合:
  - 无序、无下标、元素不可重复(HashSet、TreeSet)
- Map集合:
  - 存储一对数据,无序、无下标,键不可重复,值可以重复(HashMap、HashTable、TreeMap)
- Collections:
  - 集合工具类,定义除了存取以外的集合常用方法
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值