Collection集合

集合

概念

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

和数组区别

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

Collection集合

定义

Collection:该体系结构的根接口,代表一组对象,成为“集合”,多个⼦接⼝和实现类, 我们称之为Collection体系

Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

分类

  • List接口:有序、有下标、元素可以重复
  • Queue 队列,:除优先级外, 保持先进先出的原则
  • Set接口:无序、无下标、元素不能重复

使用

  • 添加:add(“元素”);
  • 删除:remove(“元素”);
  • 遍历:foreach或者迭代器,集合在遍历时不可以删除元素,除非迭代器删除元素
    for (Object object : collection) {
  • 迭代器:Iterator iterator = collection.iterator();
    Iterator:hasNext()、next()、remove()
  • 判断:contains(“元素”)、isEmpty()
public class Test1 {
    public static void main(String[] args) {
        //创建ArrayList
        Collection collection = new ArrayList();
        //添加
        collection.add("苹果");
        collection.add("香蕉");
        collection.add("西瓜");
       /* //查看元素个数
        System.out.println(collection.size());
        //显示集合元素值
        System.out.println(collection);

        //删除
        collection.remove("西瓜");
        System.out.println(collection);

        //清空
        collection.clear();
        System.out.println(collection.size());*/

        //遍历
       /* 第一种方案:foreach遍历
        for (Object object : collection) {
            System.out.println(object);
        }*/
        /*第二种方案:使用迭代器(迭代器专门用来遍历集合的一种方法)
         * Iterator有三个方法:
         * hasNext():如果仍有元素可以迭代,则返回 true。
         * next(): 返回迭代的下一个元素。
         * remove():删除当前元素
         * */
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            String s = (String) iterator.next();
            System.out.println(s);
            //迭代器迭代期间集合不可以删除元素,除非迭代器删除
            //collection.remove(s);  报错:java.util.ConcurrentModificationException
            //iterator.remove();  //迭代器可以删除
        }
        //System.out.println(collection.size());
/*        for (int i = 0; i < collection.size(); i++) {
            System.out.println(iterator.next());
        }*/

        //判断某个元素是否存在
        System.out.println(collection.contains("香蕉"));
        //判断集合是否为空
        System.out.println(collection.isEmpty());
    }
}

示例

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

public class Test2 {
    public static void main(String[] args) {
        //创建Collection集合
        Collection collection = new ArrayList();
        //创建Student对象
        Student student1 = new Student(21, "jack");
        Student student2 = new Student(14, "mike");
        Student student3 = new Student(19, "night");

        //添加元素
        collection.add(student1);
        collection.add(student2);
        collection.add(student3);
        //System.out.println(collection.size());
        //System.out.println(collection.toString());

        //删除元素
        //collection.remove(student1);
        //System.out.println(collection.size());
        //System.out.println(collection.toString());

        //清空元素
        //只是在集合中删除,但是student1依旧存在,删除的是student1在集合中的指针
        //collection.clear();

        //遍历元素
       /* for (Object obj:collection) {
            Student student=(Student)obj;
            System.out.println(student);
        }*/
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            Student str = (Student) iterator.next();
            System.out.println(str);
        }
    }
}

class Student {
    private int age;
    private String name;

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

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

    public Student() {
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

带All的⽅法

  • boolean addAll(Collection c) 将指定 collection 中的所有元素都添加到此 collection 中
  • boolean removeAll(Collection c) 移除此 collection 中那些也包含在指定 collection 中的所有元素
  • boolean containsAll(Collection c) 如果此 collection 包含指定 collection 中的所有元素
  • boolean retainAll(Collection c) 仅保留此 collection 中那些也包含在指定 collection 的元素
public static void main(String[] args) {
    Collection<Student> collection = new ArrayList<>();
    Student student1 = new Student("⼩红", 18);
    Student student2 = new Student("⼩明", 19);
    collection.add(student1); //添加⽅法
    collection.add(student2);
    Collection<Student> collection2 = new ArrayList<>();
    Student student3 = new Student("⼩辉", 18);
    collection2.add(student1);
    collection2.add(student3);
    //将collection2集合中的元素添加到collection集合中
    collection.addAll(collection2);
    System.out.println(collection.size());//结果: 4
    //判断collection集合中是否包含collection2集合中的所有元素
    boolean flg = collection.containsAll(collection2);
    System.out.println(flg);//结果: true
    //仅在collection中保留两个集合中相同的元素
    collection.retainAll(collection2);
    System.out.println(collection.size());//结果: 3
}

List接口

List

定义

List集合:有序、有下标、元素可以重复的

集合体系

  • ArrayList底层使用数组(线程不安全)
  • LinkedList底层使用链表
  • Vector底层使用数组(线程安全,不推荐使用)

迭代器

定义

迭代(遍历)集合中存储的元素

遍历形式
  • 获取迭代器
  • 调式hasNext()方法判断下一个元素是否存在
  • 调用next()方法获取元素
public static void main(String[] args) {
    Collection<Student> collection = new ArrayList<>();
    Student student1 = new Student("⼩红", 18);
    Student student2 = new Student("⼩明", 19);
    Student student3 = new Student("⼩辉", 18);
    collection.add(student1); //添加⽅法
    collection.add(student2);
    collection.add(student3);
    //for循环的形式
    for(Iterator<Student> it = collection.iterator();it.hasNext();){
        Student student = it.next();
        System.out.println(student);
    }
    //while循环的形式
    Iterator<Student> it = collection.iterator();
    while(it.hasNext()){
        Student student = it.next();
        System.out.println(student);
    }
}

方法

  • 创建集合:

    List list = new ArrayList();
    
  • 添加元素:
    添加:list.add(“小米”);
    指定下标位置添加:list.add(0, “华为”);

  • 删除、清空
    根据下标删除,会出现数组越界报错,否则转成Object类型\包装类
    删除(元素下标):list.remove(2);
    根据下标删除,会出现数组越界报错,否则转成Object类型\包装类

      list.remove((Object)20);
      list.remove(new Integer(20));
    

    ​ 删除(元素值)list.remove(“苹果”);

  • 清空:list.clear();

  • 遍历

    • for循环遍历:for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}

    • 增强for遍历:for (Object obj : list) {System.out.println(obj); }

    • 迭代器遍历:

          Iterator iterator=list.iterator();
          while (iterator.hasNext()){System.out.println(iterator.next());}
      
    • 列表迭代器遍历:
      正向遍历:

      ListIterator listIterator=list.listIterator();
      while (listIterator.hasNext(){System.out.println(listIterator.nextIndex(+":"+listIterator.next());}
      

      反向遍历:

      while (listIterator.hasPrevious()){System.out.println(listIterator.previousIndex()+":"+listIterator.previous());}
      
  • 判断
    判断元素:list.contains(“小米”)
    判断是否为空:list.isEmpty()

  • 获取元素值下标位置:list.indexOf(“小米”)

  • 返回子集合(前闭后开):List subList=list.subList(1,2);
    示例:

package util;

import java.util.*;

/**
* List:有序、有下标、可以重复
*/
public class Test3 {
   public static void main(String[] args) {
       //创建List集合
       List list = new ArrayList();
       
       //添加元素
       list.add("小米");
       //在指定下标位置添加元素
       list.add(0, "华为");
       list.add("苹果");
       //System.out.println(list.size());
       //System.out.println(list.toString());
       
       //删除
       //list.remove(2);   //元素下标
       //list.remove("苹果");  //元素值
       //System.out.println(list.toString());
       //清空
       //list.clear();

       //遍历
       //使用for循环遍历
       /*for (int i = 0; i < list.size(); i++) {
           System.out.println(list.get(i));
       }*/
       //使用增强for
       /*for (Object obj : list) {
           System.out.println(obj);
       }*/
       //使用迭代器遍历
      /* Iterator iterator=list.iterator();
       while (iterator.hasNext()){
           System.out.println(iterator.next());
       }*/
       //使用列表迭代器遍历str
       //可以正向、反向遍历、添加、修改、删除元素
       ListIterator listIterator=list.listIterator();
       //正向遍历
       while (listIterator.hasNext()){
           System.out.println(listIterator.nextIndex()
                   +":"+listIterator.next());
       }
       //反向遍历
       while (listIterator.hasPrevious()){
           System.out.println(listIterator.previousIndex()
                   +":"+listIterator.previous());
       }

       //判断
       System.out.println(list.contains("小米"));
       System.out.println(list.isEmpty());

       //获取位置
       System.out.println(list.indexOf("小米"));
   }
}

List实现类

ArrayList

数组结构实现,查询快、增删慢
JDK1.2版本后,运行效率快,线程不安全

1、创建对象:ArrayList arrayList = new ArrayList();
2、添加、删除、清空元素
添加:arrayList.add(30);
删除:arrayList.remove(new Integer(20));
清空:arrayList.clear();
3、遍历:fori、foreach、Iterator、ListIterator

源码分析

默认容量:DEFAULT_CAPACITY = 10;如果没有添加元素,容量是0
集合创建是默认容量为0,添加元素扩容到10,再次扩容是之前的1.5倍
存放元素的数组:elementData 
实际的元素个数:size

add()添加元素代码流程:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
        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);
    }
    
      private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        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);
    }

Vector

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

1、创建对象:Vector vector = new Vector<>();
2、添加、删除、清空元素
添加:vector.add(“草莓”);
删除:vector.remove(“香蕉”);
清空:vector.clear();
3、遍历:fori、foreach、Iterator、ListIterator、Enumeration

Enumeration enumeration=vector.elements();
while (enumeration.hasMoreElements()){
           System.out.println(enumeration.nextElement());}

LinkedList

特点

链表结构实现,增删快,查询慢

双向链表:每一个节点既记录上一个节点位置,也记录下一个节点位置

与ArrayList数组区别

  1. ArrayList --数组结构,一片连续的空间

    增删慢,查询快

    • 现有数组长度足够,末尾增加 --不存在快慢问题
    • 现有数组长度不够,末尾增加 --需要创建新数组,复制原来数组的数据,增加新元素
    • 现有长度足够,中间增加 --将指定位置之后的元素每一个向后挪动一位
    • 现有数组长度不足,中间增加 --数组扩容+挪动数组中数组的位置
  2. LinkedList --链表结构

    增删快,查改询慢

    • 增删:只需要改动前后两个节点的指向就可以将元素插入、删除
    • 查改:只有找到前一个元素,才能找到下一个元素。必须从头开始

使用

  1. 创建对象:

    LinkedList linkedList = new LinkedList();
    
  2. 添加、删除、清空元素

    • 添加

        list.add("first");
        list.add("second");
        list.add(0, "zera");
      
    • 删除

              //头部移除
              System.out.println(list.remove());
              System.out.println(list.poll());
              System.out.println(list.peekFirst());
              //尾部移除
              System.out.println(list.pollLast());
      
              //仅仅查看,不移除
              System.out.println(list.peek());
              System.out.println(list.peekFirst());
              System.out.println(list.pollLast());
      
    • 清空

      list.clear();
      
  3. 遍历:fori、foreach、Iterator、ListIterator

源码

    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++;
    }
        
    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;
        }
    }

ArrayList、Vector、LinkedList的使用演示

package util;

import java.util.*;

public class Demo1 {
    public static void main(String[] args) {
        //ArrayListTest();
        //VectorTest();
        //LinkedListTest();
    }

    /**
     * ArrayList的使用
     * 数组存储结构,遍历快,增删慢
     */
    public static void ArrayListTest() {
        //创建对象
        ArrayList arrayList = new ArrayList();

        //添加元素
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(30);
        arrayList.add(40);
        //System.out.println(arrayList.size());
        //System.out.println(arrayList.toString());

        //删除元素
        //arrayList.remove(new Integer(20));
        //System.out.println(arrayList.toString());

        //清空元素
        //arrayList.clear();

        //遍历元素
        /*for (int i = 0; i < arrayList.size(); i++) {
            System.out.println(arrayList.get(i));
        }*/
        /*for (Object obj:arrayList) {
            System.out.println(obj);
        }*/
       /* Iterator iterator=arrayList.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }*/
        //正向遍历
        ListIterator listIterator = arrayList.listIterator();
        while (listIterator.hasNext()) {
            System.out.println(listIterator.next());
        }
        //反向遍历
        while (listIterator.hasPrevious()) {
            System.out.println(listIterator.previous());
        }

        //判断元素
        System.out.println(arrayList.contains(10));
        System.out.println(arrayList.isEmpty());

        //查找
        System.out.println(arrayList.indexOf(30));
    }

    /**
     * Vector的使用
     * 数组结构
     */
    public static void VectorTest() {
        //创建对象
        Vector vector = new Vector<>();
        //添加元素
        vector.add("草莓");
        vector.add("香蕉");
        vector.add("西瓜");
        //System.out.println(vector.size());
        //System.out.println(vector.toString());

        //删除元素
        //vector.remove("香蕉");
        //vector.remove(1);
        //清空元素
        //vector.clear();

        //遍历元素
       /* for (int i = 0; i <vector.size() ; i++) {
            System.out.println(vector.get(i));
        }*/
        /*for (Object obj : vector) {
            System.out.println(obj);
        }*/
      /*  Iterator iterator=vector.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }*/
      /*  ListIterator listIterator = vector.listIterator();
        while (listIterator.hasNext()) {
            System.out.println(listIterator.next());
        }
        while (listIterator.hasPrevious()) {
            System.out.println(listIterator.previous());
        }*/
        //使用枚举器遍历
        Enumeration enumeration = vector.elements();
        while (enumeration.hasMoreElements()) {
            System.out.println(enumeration.nextElement());
        }

        //判断
        System.out.println(vector.contains("西瓜"));
        System.out.println(vector.isEmpty());
    }

    /**
     * LinkedList集合使用
     * 双向链接结构
     */
    public static void LinkedListTest() {
        //创建对象
        LinkedList linkedList = new LinkedList<>();

        //添加元素
        linkedList.add("西瓜");
        linkedList.add("草莓");
        linkedList.add("苹果");
        linkedList.add(0, "哈密瓜");
        //System.out.println(linkedList.size()+"    "+linkedList.toString());

        //删除元素
        //linkedList.remove("苹果");
        //System.out.println(linkedList.size()+"    "+linkedList.toString());

        //清空元素
        //linkedList.clear();
        //System.out.println(linkedList.size()+"    "+linkedList.toString());

        //遍历元素
        /*for (int i = 0; i <linkedList.size() ; i++) {
            System.out.println(linkedList.get(i));
        }*/
        /*for (Object o : linkedList) {
            System.out.println(o);
        }*/
       /* Iterator iterator=linkedList.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        ListIterator listIterator=linkedList.listIterator();
        while (listIterator.hasNext()){
            System.out.println(listIterator.next());
        }
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previous());
        }*/

        //判断元素
        System.out.println(linkedList.contains("南瓜"));
        System.out.println(linkedList.isEmpty());
    }
}

ArrayList和LinkedList的区别

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

常见形式有泛型类、泛型接口、泛型方法。

语法:
    ·<T...>T称为类型占位符,表示一种引用类型。
    
好处:
    ·(1)提高代码的重用性
    ·(2)防止类型转换异常,提高代码的安全性

泛型

泛型类

好处

  • 提⾼安全性(将运⾏期的错误转换到编译期)
  • 省去强转的麻烦
  • 在其作⽤域内可以统⼀参数类型

使用

语法:类名
T代表类型占位符,表示一种引用类型,如果使用多个以逗号隔开 MyGeneric<T,W,F>

  1. 使用泛型T创建变量:T t;
  2. 添加方法,使用泛型T作为方法的参数:public void show(T t) {}
  3. 使用泛型作为方法的返回值:public T getT() {return t;}

注意

  1. 泛型只能使用引用类型
  2. 不同泛型对象不能相互赋值

由来

  • 类型通过Object 转型问题引⼊
  • 早期的Object类型可以接收任意的对象类型,但是在实际的使⽤中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
public class Generic {
    private Object object;
    public Object getObject() {
        return object;
    }
    public void setObject(Object object) {
        this.object = object;
    }
}

示例:

package util;

/**
 * 泛型类
 * 语法:类名<T>
 * T代表类型占位符,表示一种引用类型,如果使用多个以逗号隔开 MyGeneric<T,W,F>
 *
 * @param <T>
 */
public class MyGeneric<T> {
    //1、使用泛型T创建变量
    T t;

    //2、添加方法,使用泛型T作为方法的参数
    public void show(T t) {
        System.out.println(t);
    }

    //3、使用泛型作为方法的返回值
    public T getT() {
        return t;
    }
}

class TestMyGeneric {
    public static void main(String[] args) {
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        myGeneric.t = "hello";
        System.out.println(myGeneric.t);
        myGeneric.show("大家好");
        String str = myGeneric.getT();

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

    }
}

通配符

泛型通配符<?>,也称为钻石通配符

  • 任意类型,如果没有明确,就是Object以及任意的Java类

    public static void main(String[] args) {
        ArrayList<String> arrayList1 = new ArrayList<>();
        ArrayList<Integer> arrayList2 = new ArrayList<>();
        List<?> list = arrayList1;
        list = arrayList2;
    }
    
  • ?extend E

    ​ 向下限定E及E的子类

  • ?super E

    ​ 向上限定E及其父类

泛型接口

格式

语法:接口名<T>
注意:不能创建泛型静态常量

接口的实现类

  1. 在创建实现类时确定实现类的类型:class Test implements MyInterfece {}
  2. 在创建实现类时不确定实现类的类型,在实例化时确定类型:class Test1 implements MyInterfece {}
/**
 * 泛型接口
 * 语法:接口名<T>
 * 不能创建泛型静态常量
 */
public interface MyInterfece<T> {
    String name = "张三";

    T servrt(T t);
}

/**
 * 接口的实现类,在创建实现类时确定实现类的类型
 */
class Test implements MyInterfece<String> {

    @Override
    public String servrt(String s) {
        System.out.println(s);
        return s;
    }
}

/**
 * 接口的实现类,在创建实现类时不确定实现类的类型,在实例化时确定类型
 *
 * @param <T>
 */
class Test1<T> implements MyInterfece<T> {

    @Override
    public T servrt(T t) {
        System.out.println(t);
        return t;
    }
}

class MyInterfeceTest {
    public static void main(String[] args) {
        Test test = new Test();
        test.servrt("zdand");

        Test1<Integer> test1 = new Test1<>();
        test1.servrt(1000);
    }
}

泛型方法

格式

语法: 返回值类型

使用

public class MyGenericMethod {
    public <T> void show(T t) {
        System.out.println("泛型方法" + t);
    }
}

class MyGenericMethodTest {
    public static void main(String[] args) {
        //T的类型由传入的数据决定
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        myGenericMethod.show(1000);
        myGenericMethod.show("中国");
    }
}

泛型集合

概念

参数化类型、类型安全的集合,强制集合元素的类型必须一致。

特点

  • ​ 编译时即可检查,而非运行时抛出异常。
  • ​ 访问时,不必类型转换(拆箱)。
  • ​ 不同泛型之间引用不能相互赋值,泛型不存在多态。

使用

package util;

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

public class Demo {
    public static void main(String[] args) {
       /* ArrayList arrayList = new ArrayList();
        //可以添加多种数据类型的数据
        arrayList.add("123");
        arrayList.add(100);
        //当遍历数据,将全部数据转换从某一种数据类型时会报错:java.lang.ClassCastException
        for (Object object : arrayList) {
            String s = (String) object;
            System.out.println(s);
        }*/
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("1231");
        //无法添加String类型外的数据,因为在创建arrayList已经确定数据类型
        //arrayList.add(1);
        for (String s : arrayList) {
            System.out.println(s);
        }
        Iterator<String> iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            String str = iterator.next();
            System.out.println(str);
        }
    }
}

泛型总结

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

常见形式有泛型类、泛型接口、泛型方法。

语法:
    ·〈T,.>T称为类型占位符,表示一种引用类型。
    
好处:
    ·(1)提高代码的重用性
    ·(2)防止类型转换异常,提高代码的安全性

Set集合

特点:无序、无下标、元素不可重复。
方法:全部继承自Collection中的方法。

1、创建集合:Set set = new HashSet<>();
2、添加元素:
添加:set.add(“小米”);
3、删除、清空
删除:set.remove(“小米”);
清空:set.clear();
4、遍历
增强for遍历:for (String s : set)
迭代器遍历:Iterator iterator = set.iterator();
5、判断
判断元素:set.contains(“小米”)
判断是否为空:set.isEmpty()

package util;

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

public class SetCollection {
   public static void main(String[] args) {
       //创建对象
       Set<String> set = new HashSet<>();

       //添加元素
       //在添加时可以添加重复的数据,但是这个数据并未到集合里去
       set.add("华为");
       set.add("小米");
       set.add("小米");
       set.add("小米");
       //System.out.println(set.size());
       //System.out.println(set.toString());

       //删除元素
       //set.remove("小米");
       //清空元素
       //set.clear();

       //遍历元素
       //增强for
       for (String s : set) {
           System.out.println(s);
       }
       //迭代器遍历
       Iterator iterator = set.iterator();
       while (iterator.hasNext()) {
           System.out.println(iterator.next());
       }

       //判断
       System.out.println(set.isEmpty());
       System.out.println(set.contains("小米"));
   }
}

Set实现类

HashSet

基于HashCode计算元素存放位置。
当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。

创建对象:HashSet<String> set = new HashSet<>();
(备注:其他的与set一致)
存储过程
1、根据hashcode计算保存的位置,如果此位置为空,直接保存,如果不为空执行第二步
2、执行equals(),如果equals()为true,则认为重复,否则形成链表
equals()和hashcode()重写

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

    public Person() {
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    /**
     * 重写hashCode
     *
     * @return
     */
    @Override
    public int hashCode() {
        int n1 = this.name.hashCode();
        int n2 = this.age;
        return n1 + n2;
    }

    /**
     * 重写equals
     *
     * @param o
     * @return
     */
    @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 (this.name.equals(person.getName()) && this.age == person.getAge()) {
                return true;
            }
        }
        return false;
    }
}

TreeSet

定义
  • 实现了SortedSet接口,对元素的大小进行排序,形成一个树状结构(红黑树),元素是不可以重复存在的

  • 存入的元素必须实现Comparable接口,并且重写compareTo()

    SortedSet()源码

    public interface SortedSet<E> extends Set<E> {
        Comparator<? super E> comparator();
    }
    public interface Comparator<T> {
    	int compare(T o1, T o2);
    }
    
构造方法
  • TreeSet() 构造⼀个新的空set, 该set根据其元素的⾃然顺序进⾏排序
  • TreeSet(Comparator <? super E> comparator) 构建⼀个空的TreeSet, 他根据指定⽐较器进⾏排序
常用方法
  • add(E e) 将指定元素添加到此set

  • first() 返回此set中当前第⼀元素

  • last() 返回此set中当前最后⼀个元素

  • floor() 返回此set中⼩于等于给定元素的最⼤元素,不存在则返回null

  • higher() 返回此set中严格⼤于给定元素的最⼩元素,不存在则返回null

    import java.util.SortedSet;
    import java.util.TreeSet;
    
    public class TreeSetDemo {
        public static void main(String[] args) {
            TreeSet<Integer> treeSet = new TreeSet<Integer>();
            treeSet.add(1);
            treeSet.add(23);
            treeSet.add(423);
            treeSet.add(14);
            treeSet.add(67);
    
            for (Object o : treeSet) {
                System.out.print(o + "\t");
            }
    
            //获取集合中小于给定数据的最大元素,如果无返回null
            System.out.println(treeSet.floor(54));
            //获取集合中大于给定数据的最小元素,如果无返回null
            System.out.println(treeSet.higher(54));
    
            System.out.println(treeSet.first());//首个元素
            System.out.println(treeSet.last());//最后一个元素
            System.out.println(treeSet.size());//长度
            System.out.println(treeSet.pollFirst());//移除第一个元素
            System.out.println(treeSet.pollLast());//移除最后一个元素
        }
    }
    

添加原理

TreeSet会将第⼀个添加的元素作为中点, 以后添加的元素会先跟中点进⾏⽐较, 如果⼤于就接着跟所⽐较元素的右边的元素接着⽐较,如果⼩于就接着跟所⽐较元素左边的元素接着⽐较, 直到⽆法找到可⽐较的元素,就会将新添加的这个元素放到当前位置

注意事项
  • TreeSet集合的存储原理限定了必须要对存入的元素进行比较
  • 元素要么实现Comparable接口,要么实现Comparator接口,否则程序报错

Comparable

当TreeSet集合添加引用类型(不是int这些基础和String等,是个人写的某个类)数据时,会报:类型转换失败的错误,如下:

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

    public Person() {
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

public class SetCollection {
    public static void main(String[] args) {
        //创建对象
        TreeSet<Person> set = new TreeSet<>();
        Person person1 = new Person(11, "jack");
        Person person2 = new Person(12, "son");
        Person person3 = new Person(20, "mkisq");
        set.add(person1);
        set.add(person2);
        set.add(person3);
        System.out.println(set.toString());
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ie3C2r9-1645535987110)(F:\笔记文件\JavaSE\12、集合\集合.assets\image-20210924101423240.png)]

为什么:
因为TreeSet的存储结构时红黑树,数据需要比较,而Person数据无法比较,导致数据全部在一边,失去平衡。

当集合中的元素比较时,然后集合没有比较器,元素就会转成Comparator类型并调用comparaTo(),所以我们必须重写

compareTo
  • 返回值小于0,表示当前元素小于被比较元素
  • 返回值等于0,表示当前元素等于被比较元素
  • 返回值大于0,表示当前元素大于被比较元素

处理方法:
Person实现Comparable接口,并且重写compareTo方法:比较数据大小

public class Person implements Comparable<Person> {
    /**
     * 重写compareTo方法
     * 比较数据大小:先比name,后比age
     *
     * @param o
     * @return
     */
    @Override
    public int compareTo(Person o) {
        int n1 = this.getName().compareTo(o.getName());
        int n2 = this.age - o.getAge();
        return n1 == 0 ? n2 : n1;
    }
}

Comparator

comparator是一个接口,需要重写compare()

    public static void main(String[] args) {
        //创建对象
        TreeSet<Person> set = 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 n2 == 0 ? n1 : n2;
            }
        });
    }

Collections

Map集合

Map接口的特点

  1. 用于存储任意键值对(key-value)
  2. 键:无序、无下标、不允许重复(唯一)
  3. 值:无序、无下标、允许重复

Map父接口常用方法

  1. V put(K key,,V value):将对象存入到集合中,关联键值。key重复则覆盖原值。

  2. Object get(Object key):根据键获取对应的值。

  3. Set:返回所有key。

  4. Collectionvalues():返回包含所有值的Collection集合。

  5. Set<Map.Entry<K,V>> :键值匹配的Set集合。

    public class MapDemo {
        public static void main(String[] args) {
            //创建
            Map<Integer, String> map = new HashMap<>();
            //添加元素 K V
            map.put(1, null);
            map.put(null, "pear");
            map.put(3, "new oranage");
            map.put(3, "oranage");//替换某个位置的value值
            
            System.out.println(map.get(122));//这里没有报错是数据没有进行处理
            System.out.println(reData(map.get(122)));//对数据处理,提示空指针错误
            
            //键与值是否相关联,如果没有返回null(只关心key是否有值,如果没有返回null)
            System.out.println(map.putIfAbsent(1, "111"));
            //判断键值是否存在
            System.out.println("111".equals(map.getOrDefault(5, "111")) ? "无" : "111");
            
            System.out.println(map.get(3));//获取某个key上的value,不存在返回null
            System.out.println(map.isEmpty());//判断map是否为空
            System.out.println(map.containsKey(2));//判断map中是否有指定的key
            System.out.println(map.containsValue("xi"));//判断map中是否有指定的value
            System.out.println(map.entrySet());//查看所有数据
            System.out.println(map.keySet());//查看所有的key
            map.putAll(map);//添加map集合
            System.out.println(map.remove(3));//移除执行key和对应的value
            System.out.println(map.size());//返回长度
            System.out.println(map.values());//查看所有的value
            map.clear(); //清空元素
          
            HashMap<Integer,String> hashMap=(HashMap<Integer, String>) ((HashMap<Integer, String>) map).clone();//返回此 HashMap实例的浅拷贝:键和值本身不被克隆
        }
    
        public static String reData(String s) {
            return s.toUpperCase().substring(0);
        }
    }
    

forEach、增强for

定义

  • Iterator的简写形式
  • 简化数组和Collection集合的遍历

格式

for(元素数据类型	变量	:	数组或Collection集合){
	使用变量即可,变量就是元素	
}
public static void main(String[] args) {
    TreeSet<Student> set = new TreeSet<>(new MyComparator());
    Student student1 = new Student("⼩红");
    Student student2 = new Student("⼩明");
    Student student3 = new Student("⼩李");
    set.add(student1);
    set.add(student2);
    set.add(student3);
    for (Student student : set) {
        System.out.println(student);
    }
}

迭代方式的删除

  • 普通for循环,可以删除,但是需要角标
  • 迭代器,可以删除,但是必须使用迭代器自身的remove(),否则会并发修改异常
    ap.containsKey(2));//判断map中是否有指定的key
    System.out.println(map.containsValue(“xi”));//判断map中是否有指定的value
    System.out.println(map.entrySet());//查看所有数据
    System.out.println(map.keySet());//查看所有的key
    map.putAll(map);//添加map集合
    System.out.println(map.remove(3));//移除执行key和对应的value
    System.out.println(map.size());//返回长度
    System.out.println(map.values());//查看所有的value
    map.clear(); //清空元素
            HashMap<Integer,String> hashMap=(HashMap<Integer, String>) ((HashMap<Integer, String>) map).clone();//返回此 HashMap实例的浅拷贝:键和值本身不被克隆
        }
    
        public static String reData(String s) {
            return s.toUpperCase().substring(0);
        }
    }
    

forEach、增强for

定义

  • Iterator的简写形式
  • 简化数组和Collection集合的遍历

格式

for(元素数据类型	变量	:	数组或Collection集合){
	使用变量即可,变量就是元素	
}
public static void main(String[] args) {
    TreeSet<Student> set = new TreeSet<>(new MyComparator());
    Student student1 = new Student("⼩红");
    Student student2 = new Student("⼩明");
    Student student3 = new Student("⼩李");
    set.add(student1);
    set.add(student2);
    set.add(student3);
    for (Student student : set) {
        System.out.println(student);
    }
}

迭代方式的删除

  • 普通for循环,可以删除,但是需要角标
  • 迭代器,可以删除,但是必须使用迭代器自身的remove(),否则会并发修改异常
  • 超级for循环不能删除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值