集合框架

集合

什么是集合?

  • 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
  • 和数组区别:
    • (1)数组长度固定,集合长度不固定
    • (2)数组可以存储基本类型和引用类型,集合只能存储引用类型
  • 位置:java.util.*;

Collection体系集合

image

  • Interface Collection:该体系结构的根接口,代表一组对象,称为“集合”。
  • List接口的特点:有序、有下标、元素可重复
  • Set接口的特点:无序、无下标、元素不能重复

Collection父接口

  • 特点:代表一组任意类型的对象,无序、无下标、不能重复。

  • 方法:

    • boolean add(Object obj) //添加一个对象
    • boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中
    • void clear() //清空此集合中的所有对象
    • boolean contains(Object o) //检查此集合中是否包含o对象
    • boolean equals(Object o) //比较此集合是否与指定对象相等
    • boolean isEmpty() //判断此集合是否为空
    • boolean remove(Object o) //在此集合中移除o对象
    • int size() //返回此集合中的元素个数
    • Object[] toArray() //将此集合转换成数组
    package com.aggregation.demo01;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    /**
     * Collection接口的使用
     * (1)添加元素
     * (2)删除元素
     * (3)遍历元素
     * (4)判断
     * @author 大白很白
     */
    public class demo01 {
        public static void main(String[] args) {
            //创建集合
            Collection collection=new ArrayList();
            //(1)添加元素
            collection.add("苹果");
            collection.add("西瓜");
            collection.add("榴莲");
            System.out.println("元素个数:"+collection.size());
            System.out.println(collection);
            //(2)删除元素
            //collection.remove("榴莲");
            //collection.clear();
            //System.out.println("删除之后:"+collection.size());
    
            //(3)遍历元素【重点】
            //3.1 使用增强for
            System.out.println("------------------3.1 使用增强for-----------------------");
            for (Object object : collection){
                System.out.println((String) object);
            }
            //3.2 使用迭代器(迭代器专门用来遍历集合的一种方式)
            //hasNext();有没有下一个元素
            //next();获取下一个元素
            //remove();删除当前元素
            System.out.println("------------------3.2 使用增强for-----------------------");
            Iterator it = collection.iterator();
            while(it.hasNext()){
                String s = (String) it.next();
                System.out.println(s);
               // collection.remove(s);//不能在迭代器内使用collection.remove()方法,不可并发修改
                //it.remove();
            }
            System.out.println("元素个数:"+collection.size());//元素个数:0
    
            //(4)判断
            System.out.println(collection.contains("西瓜"));
            System.out.println(collection.isEmpty());
    
    
    
        }
    }
    
  • Collection的使用:保存学生信息

    Student.java

    package com.aggregation.demo01;
    
    /**
     * 学生类
     * @ author 大白很白
     */
    public class Student {
        private String name;
        private int age;
        public Student(){
    
        }
    
        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 +
                    '}';
        }
    }
    

    Demo02.java

    package com.aggregation.demo01;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    /**
     * Collection的使用:保存学生信息
     * @ author 大白很白
     */
    public class Demo02 {
        public static void main(String[] args) {
            //新建Collection对象
            Collection collection = new ArrayList();
            Student s1 = new Student("张三",16);
            Student s2 = new Student("李四",20);
            Student s3 = new Student("小王",18);
            //1添加数据
            collection.add(s1);
            collection.add(s2);
            collection.add(s3);
            System.out.println("元素个数:"+collection.size());
            System.out.println(collection.toString());
    
            //2删除
            collection.remove(s1);
            //collection.clear();//清除集合中的元素,集合中保存的实际是对象的地址,对象和集合之间指针指向
            //System.out.println("删除之后:"+collection.size());
    
            //3遍历
            //3.1 增强for
            System.out.println("------------------3.1 增强for-------------------------");
            for ( Object object:collection) {
                Student s = (Student)object;
                System.out.println(s.toString());
            }
            //3.2 迭代器:hasNext(); next(); remove();迭代过程中不能使用collection的删除方法
            Iterator it = collection.iterator();
            while(it.hasNext()){
                Student s=(Student)it.next();
                System.out.println(s.toString());
            }
            //4 判断
            System.out.println(collection.contains(s1));
            System.out.println(collection.isEmpty());
        }
    
    }
    
  • 迭代器

image

List子接口

  • 特点:有序、有下标、元素可以重复。

  • 方法:

    • void add(int index, Object o) //在index位置插入对象o

    • boolean addAll(int index, Collection c) //将一个集合中的元素添加到此集合中的index位置

    • Object get(int index) //返回集合中指定位置的元素

    • List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的集合元素

      package com.aggregation.demo01;
      
      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.List;
      import java.util.ListIterator;
      
      /**
       * List子接口的使用
       * 特点:1 有序 有下表 2 可以重复
       * @ author 大白很白
       */
      public class Demo03 {
          public static void main(String[] args) {
              //先创建集合对象
              List list = new ArrayList<>();
              //1添加元素
              list.add("苹果");
              list.add("小米");
              list.add(0,"华为");
              System.out.println("元素个数:"+list.size());//元素个数:3
              System.out.println(list.toString());//[华为, 苹果, 小米]
              //2删除元素
              //list.remove(0);
              System.out.println("删除之后:"+list.size());//删除之后:3
              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 object:list) {
                  System.out.println(object);
                  /*
                  华为
                  苹果
                  小米
                   */
              }
              //3.3使用迭代器
              System.out.println("---------------------3.3使用迭代器-----------------------");
              Iterator it = list.iterator();
              while(it.hasNext()){
                  System.out.println(it.next());
                   /*
                  华为
                  苹果
                  小米
                   */
              }
              //3.4使用列表迭代器,和Iterator的区别,ListIterator可以向前或者向后遍历,添加、删除、修改元素
              ListIterator lit = list.listIterator();
              System.out.println("---------------------3.4使用列表迭代器从前往后-----------------------");
              while(lit.hasNext()){
                  System.out.println(lit.nextIndex()+":"+lit.next());
                  /*
                  0:华为
                  1:苹果
                  2:小米
                   */
              }
              System.out.println("---------------------3.4使用列表迭代器从后往前-----------------------");
              while(lit.hasPrevious()){
                  System.out.println(lit.previousIndex()+":"+lit.previous());
                  /*
                  2:小米
                  1:苹果
                  0:华为
                   */
              }
              //4判断
              System.out.println(list.contains("苹果"));//true
              System.out.println(list.isEmpty());//false
      
              //5获取位置
              System.out.println(list.indexOf("华为"));//0
          }
      }
      
      
    • list添加数字数据

      package com.aggregation.demo01;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public class Demo04 {
          public static void main(String[] args) {
              //创建集合
              List list = new ArrayList<>();
              //1添加数字数据(自动装箱)
              list.add(20);
              list.add(30);
              list.add(40);
              list.add(50);
              list.add(60);
              System.out.println("元素个数:"+list.size());//元素个数:5
              System.out.println(list.toString());//[20, 30, 40, 50, 60]
              //2删除操作
              //list.remove(0);
              //list.remove(new Integer(20));//(Object)20
              System.out.println("删除元素:"+list.size());//删除元素:5
              System.out.println(list.toString());//[20, 30, 40, 50, 60]
      
              //3补充方法subList:返回子集合,含头不含尾
              List subList = list.subList(1, 3);
              System.out.println(subList.toString());//[30, 40]
      
          }
      }
      

List实现类

  • ArrayList【重点】:
    • 数组结构实现,查询快、增删慢;
    • JDK1.2版本,运行效率快、线程不安全。
  • Vector:
    • 数组结构实现,查询快、增删慢;
    • JDK1.0版本,运行效率慢、线程安全。
  • LinkedList:
    • 链表结构实现,增删快,查询慢。
    • 链表:!image

ArrayList的使用

  • Student.java 重写了equals方法

    package com.aggregation.demo01;
    
    /**
     * 学生类
     * @ author 大白很白
     */
    public class Student {
        private String name;
        private int age;
        public Student(){
    
        }
    
        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 s = (Student)obj;
                //比较属性
                if (this.name.equals(s.getName())&&this.age==s.getAge()){
                    return true;
                }
            }
            //5不满足条件返回false
            return false;
        }
    }
    
  • ArrayList的使用

    package com.aggregation.demo01;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.ListIterator;
    
    /**
     * ArrayList的使用
     * 存储结构:数组,查找遍历速度快,增删慢
     */
    public class Demo05 {
        public static void main(String[] args){
            //1添加元素
            ArrayList<Object> arrayList = new ArrayList<>();
            Student s1 = new Student("王德发",20);
            Student s2 = new Student("光头强",22);
            Student s3 = new Student("赵四",18);
            arrayList.add(s1);
            arrayList.add(s2);
            arrayList.add(s3);
            System.out.println("元素个数:"+arrayList.size());//元素个数:3
            System.out.println(arrayList.toString());//[Student{name='王德发', age=20}, Student{name='光头强', age=22},
                                                    // Student{name='赵四', age=18}]
            //2删除元素
            //arrayList.remove(s1);
            //arrayList.remove(new Student("王德发",20));//重写了equals方法
            //System.out.println("删除之后:"+arrayList.size());//删除之后:2
            //3遍历元素【重点】
            //3.1使用迭代器
            System.out.println("-------------3.1使用迭代器------------------");
            Iterator<Object> it = arrayList.iterator();
            while(it.hasNext()){
                Student s = (Student) it.next();
                System.out.println(s.toString());
                /*
                Student{name='王德发', age=20}
                Student{name='光头强', age=22}
                Student{name='赵四', age=18}
                 */
            }
            //3.2列表迭代器
            System.out.println("-------------3.2使用列表迭代器------------------");
            ListIterator<Object> lit = arrayList.listIterator();
            while(lit.hasNext()){
                Student s = (Student) lit.next();
                System.out.println(s.toString());
                /*
                Student{name='王德发', age=20}
                Student{name='光头强', age=22}
                Student{name='赵四', age=18}
                 */
            }
            System.out.println("-------------3.2使用列表迭代器逆序------------------");
            while(lit.hasPrevious()){
                Student s = (Student) lit.previous();
                System.out.println(s.toString());
                /*
                Student{name='赵四', age=18}
                Student{name='光头强', age=22}
                Student{name='王德发', age=20}
                 */
            }
            //4判断
            // System.out.println(arrayList.contains(s1));
            System.out.println(arrayList.contains(new Student("光头强",22)));//true,重写了equals方法
            System.out.println(arrayList.isEmpty());//false
            //5查找
            //System.out.println(arrayList.indexOf(s1));
            System.out.println(arrayList.indexOf(new Student("赵四",18)));//2
        }
    
    }
    

ArrayList源码分析

源码分析:DEFAULT_CAPACITY = 10; 默认容量

​ 注意:如果没有向集合中添加任何元素时,容量为0;添加一个元素后,容量为10

​ 每次扩容的大小为原来的1.5倍

​ EMPTY_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 static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return 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集合的使用

package com.aggregation.demo02;

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

/**
 * 演示Vector集合的使用
 * 存储结构:数组
 * @author 大白很白
 */
public class Demo01 {
    public static void main(String[] args) {
        //1创建集合
        Vector vector = new Vector();
        //添加元素
        vector.add("草莓");
        vector.add("芒果");
        vector.add("西瓜");
        System.out.println("元素个数:"+vector.size());
        //2删除
        //vector.remove(0);
        //vector.remove("西瓜");
        //vector.clear();
        //3遍历
        //使用枚举器
        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());
        //5 vector其他方法
        //firstElement、lastElement、elementAt();


    }
}

LinkedList的使用

package com.aggregation.demo02;

import com.aggregation.demo01.Student;

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

/**
 * LinkedList的使用
 * 存储结构:双向链表
 * @author 大白很白
 */
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        LinkedList<Object> linkedList = new LinkedList<>();
        //1添加元素
        Student s1 = new Student("王德发",20);
        Student s2 = new Student("光头强",22);
        Student s3 = new Student("赵四",18);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        linkedList.add(s3);
        System.out.println("元素个数:"+linkedList.size());
        System.out.println(linkedList.toString());

        //2删除
        //linkedList.remove(s1);
        //System.out.println("删除之后:"+linkedList.size());
        //linkedList.clear();
        //3遍历
        //3.1for遍历
        System.out.println("--------------for------------");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
        //3.2增强for
        System.out.println("--------------增强for-------------");
        for (Object object:linkedList) {
            Student s = (Student) object;
            System.out.println(s.toString());
        }
        //3.3使用迭代器
        System.out.println("--------------使用迭代器-------------");
        Iterator<Object> it = linkedList.iterator();
        while (it.hasNext()){
            Student s = (Student) it.next();
            System.out.println(s.toString());
        }
        //3.4使用列表迭代器
        System.out.println("--------------使用列表迭代器-------------");
        ListIterator<Object> listIterator = linkedList.listIterator();
        while (listIterator.hasNext()){
            Student s = (Student) listIterator.next();
            System.out.println(s.toString());
        }
        //4判断
        System.out.println(linkedList.contains(s1));
        System.out.println(linkedList.isEmpty());
        //5获取
        System.out.println(linkedList.indexOf(s1));//下标0


    }
}

LinkedList源码分析

Node first;链表的头节点

Node last;链表的尾节点

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和LinkedList区别

image

LinkedList 双向链表 或从尾到头

ArrayList:必须开辟连续空间,查询快,增删慢。

LinkedList:无需开辟连续空间,查询慢,增删快。

泛型

  • Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
  • 常见形式有泛型类、泛型接口、泛型方法。
  • 语法:
    • <T,...>T称为类型占位符,表示一种引用类型。
  • 好处:
    • (1)提高代码的重用性
    • (2)防止类型转换异常,提高代码的安全性

泛型类

MyGeneric.java

package com.aggregation.demo02;

/**
 * 泛型类
 * 语法:类名<T>
 * T是类型占位符,表示一种引用类型,如果编写多个,使用逗号隔开
 * @author 大白很白
 */
public class MyGeneric<T> {
    //使用泛型T
    //1创建变量
    T t;

    //2泛型作为方法的参数
    public void show(T t){
        System.out.println(t);
    }
    //3使用泛型作为方法的返回值
    public T getT(){
        return t;
    }


}

TestGeneric.java

package com.aggregation.demo02;

public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类创建对象
        //注意:1泛型只能使用引用类型,2不同泛型对象之间不能相互复制
        MyGeneric<String> myGeneric = new MyGeneric<String>();//后面的String可写可不写,JDK1.7之前必须写
        myGeneric.t="hello";
        myGeneric.show("大家好,加油");
        String string = myGeneric.getT();

        MyGeneric<Integer> myGeneric2 = new MyGeneric<>();
        myGeneric2.t=100;
        myGeneric2.show(200);
        Integer integer = myGeneric2.getT();
    }
}

泛型接口

MyInterface.java

package com.aggregation.demo02;

/**
 * 泛型接口
 * 语法:接口名<T>
 * 注意:不能创建泛型静态常量
 * @author 大白很白
 * @param <T>
 */
public interface MyInterface<T> {
    String name="罗小通";
    T server(T t);

}

MyInterfaceImpl.java

package com.aggregation.demo02;

public class MyInterfaceImpl implements MyInterface<String>{//泛型需设置一个类型

    @Override
    public String server(String t) {
        System.out.println(t);
        return t;
    }
}

MyInterfaceImpl2.java

package com.aggregation.demo02;

public class MyInterfaceImpl2<T> implements MyInterface<T> {//暂未指定类型,可使用时再指定
    @Override
    public T server(T t) {
        System.out.println(t);
        return t;
    }
}

TestMyInterface.java

package com.aggregation.demo02;

public class TestMyInterface {
    public static void main(String[] args) {
        MyInterfaceImpl impl1 = new MyInterfaceImpl();
        impl1.server("你充q币吗");

        MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<>();
        impl2.server(1000);

    }
}

泛型方法

MyGenericMethod.java

package com.aggregation.demo02;

/**
 * 泛型方法
 * 语法:<T>返回值类型
 * @author 大白很白
 */
public class MyGenericMethod {

    //泛型方法
    public <T> T show(T t){
        System.out.println("泛型方法:"+t);
        return t;
    }

}

TestMyGenericMethod

package com.aggregation.demo02;

public class TestMyGenericMethod {
    public static void main(String[] args) {
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        myGenericMethod.show("加油加油!");//泛型方法:加油加油!
        myGenericMethod.show(200);//泛型方法:200
        myGenericMethod.show(3.14);//泛型方法:3.14
    }
}

泛型集合

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

  • 特点:

    • 编译时即可检查,而非运行时抛出异常。
    • 访问时,不必类型转换(拆箱)。
    • 不同泛型之间引用不能相互赋值,泛型不存在多态。
    package com.aggregation.demo02;
    
    import com.aggregation.demo01.Student;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Demo03 {
        public static void main(String[] args) {
            ArrayList<Student> arrayList = new ArrayList<Student>();
            Student s1 = new Student("王德发",20);
            Student s2 = new Student("光头强",22);
            Student s3 = new Student("赵四",18);
            arrayList.add(s1);
            arrayList.add(s2);
            arrayList.add(s3);
    
            Iterator<Student> it = arrayList.iterator();
            while (it.hasNext()){
                Student s = it.next();
                System.out.println(s.toString());
            }
        }
    }
    

Set子接口

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

Set实现类

  • HashSet【重点】:
    • 基于HashCode实现元素不重复。
    • 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
  • TreeSet:
    • 基于排列顺序实现元素不重复。
    • 实现了SortedSet接口,对集合元素自动排序。
    • 元素对象的类型必须实现Comparable接口,指定排序规则。
    • 通过ComparaTo方法确定是否为重复元素。

Set接口的使用

package com.aggregation.demo03;

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

/**
 * 测试Set接口的使用
 * 特点:(1)无序、没有下标 (2)不能重复
 * @大白很白
 */
public class Demo01 {
    public static void main(String[] args) {
        //创建集合
        HashSet<String> set = new HashSet<>();
        //1添加数据
        set.add("苹果");
        set.add("华为");
        set.add("小米");
        System.out.println("数据个数:"+set.size());
        System.out.println(set.toString());
        //2删除数据
        //set.remove("苹果");
        //System.out.println(set.toString());
        //3遍历【重点】
        //3.1增强for
        System.out.println("-------------增强for--------");
        for (String string:set) {
            System.out.println(string);
        }
        //3.2使用迭代器
        System.out.println("-----------使用迭代器-------------");
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //4判断
        System.out.println(set.contains("华为"));
        System.out.println(set.isEmpty());


    }

}

HashSet的使用

Demo02

package com.aggregation.demo03;

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

/**
 * HashSet集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * @ author 大白很白
 */
public class Demo02 {
    public static void main(String[] args) {
        //新建集合
        HashSet<String> hashSet = new HashSet<>();
        //1添加元素
        hashSet.add("罗通");
        hashSet.add("罗小通");
        hashSet.add("杨玉珍");
        hashSet.add("老兰");
        System.out.println("元素个数:"+hashSet.size());
        System.out.println(hashSet.toString());
        //2删除数据
        //hashSet.remove("老兰");
        //System.out.println("删除以后:"+hashSet.size());
        //3遍历操作
        //3.1增强for
        System.out.println("------------3.1增强for----------");
        for (String string:hashSet) {
            System.out.println(string);
        }
        //3.2使用迭代器
        System.out.println("-------------3.2使用迭代器---------------");
        Iterator<String> it = hashSet.iterator();
        while (it.hasNext()){
            //String s = it.next();
            //System.out.println(s);
            System.out.println(it.next());
        }
        //4判断
        System.out.println(hashSet.contains("老兰"));
        System.out.println(hashSet.isEmpty());


    }
}

Demo03.java

package com.aggregation.demo03;

import java.util.HashSet;

/**
 * HashSet的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * @author 大白很白
 */
public class Demo03 {
    public static void main(String[] args) {
        //创建集合
        HashSet<Person> persons = new HashSet<>();
        //1添加数据
        Person p1 = new Person("小红",18);
        Person p2 = new Person("小绿",19);
        Person p3 = new Person("小黑",20);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);

        System.out.println("元素个数:"+persons.size());
        System.out.println(persons.toString());



    }
}

Person.java

package com.aggregation.demo03;

/**
 * 人类
 * @author 大白很白
 */
public class Person {
    private String name;
    private int 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;
    }

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

    public Person() {
    }

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

HashSet存储方式

存储过程

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

手动重写hashcode和equals

package com.aggregation.demo03;

/**
 * 人类
 * @author 大白很白
 */
public class Person {
    private String name;
    private int 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;
    }

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

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;

        return n1+n2;
    }

    @Override
    public boolean equals(Object obj) {
        if (this==obj){
            return true;
        }
        if (obj==null){
            return false;
        }
        if (obj instanceof Person){
            Person p = (Person)obj;

            if (this.name.equals(p.getName())&&this.age==p.getAge()){
                return true;
            }
        }
        return false;
    }
}

使用快捷键重写hashcode和equals:Alt+Insert

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return getAge() == person.getAge() && Objects.equals(getName(), person.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getAge());
    }

理解存储过程(重复判断依据)

package com.aggregation.demo03;

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

/**
 * HashSet的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 存储过程
 * 1. 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
 * 2. 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
 * @author 大白很白
 */
public class Demo03 {
    public static void main(String[] args) {
        //创建集合
        HashSet<Person> persons = new HashSet<>();
        //1添加数据
        Person p1 = new Person("小红",18);
        Person p2 = new Person("小绿",19);
        Person p3 = new Person("小黑",20);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);

        persons.add(new Person("小红",18));//重写了hashcode,equals

        System.out.println("元素个数:"+persons.size());
        System.out.println(persons.toString());


        //2删除操作
        //persons.remove(p1);
        //persons.remove(new Person("小红",18));
        //System.out.println("删除之后:"+persons.size());

        //3遍历【重点】
        //3.1使用增强for
        for (Person person:persons) {
            System.out.println(person.toString());
        }

        //3.2使用迭代器
        System.out.println("--------------------------");
        Iterator<Person> it = persons.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //4判断
        System.out.println(persons.contains(new Person("小黑",20)));
        System.out.println(persons.isEmpty());


    }
}

TreeSet的使用

存储String类型

Demo04.java

package com.aggregation.demo03;

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

/**
 * TreeSet的使用
 * 存储结构:红黑树
 * @author 大白很白
 */
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("xyz");//元素不重复,未添加
        System.out.println("元素个数:"+treeSet.size());
        System.out.println(treeSet.toString());

        //2删除
        //treeSet.remove("xyz");
        //System.out.println("删除之后:"+treeSet.toString());

        //3遍历
        //3.1增强for
        System.out.println("------------------------");
        for (String string:treeSet) {
            System.out.println(string);
        }
        //3,2使用迭代器
        System.out.println("-----------------------");
        Iterator<String> it = treeSet.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //4判断
        System.out.println(treeSet.contains("abc"));
        System.out.println(treeSet.isEmpty());
    }
}

保存Person类型

需实现Comparable接口

Person.java

package com.aggregation.demo03;

import java.util.Objects;

/**
 * 人类
 * @author 大白很白
 */
public class Person implements Comparable<Person>{
    @Override
    public int compareTo(Person o) {
        int n1=this.getName().compareTo(o.getName());
        int n2=this.age-o.getAge();
        return n1==0?n2:n1;//如果n1=0,返回n2,否则返回n1
    }

    private String name;
    private int 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;
    }

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

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
//    @Override
//    public int hashCode() {
//        int n1=this.name.hashCode();
//        int n2=this.age;
//
//        return n1+n2;
//    }
//
//    @Override
//    public boolean equals(Object obj) {
//        if (this==obj){
//            return true;
//        }
//        if (obj==null){
//            return false;
//        }
//        if (obj instanceof Person){
//            Person p = (Person)obj;
//
//            if (this.name.equals(p.getName())&&this.age==p.getAge()){
//                return true;
//            }
//        }
//        return false;
//    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return getAge() == person.getAge() && Objects.equals(getName(), person.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getAge());
    }
}

Demo05.java

package com.aggregation.demo03;

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

/**
 * 使用TreeSet保存数据
 * 存储结构:红黑树
 * 要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
 * @author 大白很白
 */
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<Person> persons = new TreeSet<>();
        //1添加元素
        Person p1 = new Person("xyz",18);
        Person p2 = new Person("hello",19);
        Person p3 = new Person("zz",20);
        Person p4 = new Person("zz",21);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        persons.add(p4);
        System.out.println("元素个数:"+persons.size());
        System.out.println(persons.toString());
        //元素个数:4
        //[Person{name='hello', age=19}, Person{name='xyz', age=18}, Person{name='zz', age=20}, Person{name='zz', age=21}]

        //2删除
        //persons.remove(p1);
        //persons.remove(new Person("xyz",18));
        //System.out.println("删除之后:"+persons.size());

        //3遍历
        //3.1使用增强for
        for (Person person:persons) {
            System.out.println(person);
        }
        //3.2使用迭代器
        System.out.println("------------------------");
        Iterator<Person> it = persons.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        //4判断
        System.out.println(persons.contains(p1));
        System.out.println(persons.isEmpty());

    }
}

Comparator接口

Comparator:实现定制比较(比较器)

Demo06.java

package com.aggregation.demo03;

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

/**
 * TreeSet集合的使用
 * Comparator:实现定制比较(比较器)
 * Comparable:可比较的
 * @author 大白很白
 */
public class Demo06 {
    public static void main(String[] args) {
        //创建集合,并指定比较规则
        TreeSet<Person> persons = 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;
            }
        });
        Person p1 = new Person("xyz",18);
        Person p2 = new Person("hello",19);
        Person p3 = new Person("zz",20);
        Person p4 = new Person("dd",20);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        persons.add(p4);
        System.out.println(persons.toString());

    }
}

TreeSet案例

要求:使用TreeSet集合实现字符串按照长度进行排序

Demo07.java

package com.aggregation.demo03;

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

/**
 * 要求:使用TreeSet集合实现字符串按照长度进行排序
 * helloworld zhang lisi wangwwu beijing xian nanjing
 * Comparator接口实现定制比较
 */
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;
            }
        });
        //添加数据
        treeSet.add("helloworld");
        treeSet.add("cat");
        treeSet.add("superman");
        treeSet.add("puppy");
        treeSet.add("lightning");
        treeSet.add("ball");
        System.out.println(treeSet.toString());
    }
}

Map集合

image

map接口的特点:

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

Map父接口

  • 特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复
  • 方法:
    • V put(K key,V value) //将对象存入到集合中,关联键值。key重复则覆盖原值。
    • Object get(Object key) //根据键获取对应的值。
    • Set //返回所有Key。
    • Collectionvalues() //返回包含所有值的Collection集合。
    • Set<Map.Entry<K,V>> //键值匹配的Set集合。

Map接口的使用

image

Demo01.java

package com.aggregation.demo04;

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

/**
 * Map接口的使用
 * 特点:(1)存储键值对(2)键不能重复,值可以重复(3)无序
 * @author 大白很白
 */
public class Demo01 {
    public static void main(String[] args) {
        //创建Map集合
        Map<String, String> map = new HashMap<>();
        //1添加元素
        map.put("cn","中国");
        map.put("uk","英国");
        map.put("usa","美国");
        map.put("cn","zhongguo");//元素并未增加,但值会覆盖

        System.out.println("元素个数:"+map.size());
        System.out.println(map.toString());

        //2删除
//        map.remove("usa");
//        System.out.println("删除之后:"+map.size());

        //3遍历
        //3.1使用keySet();
        System.out.println("---------------keySet()-------------------");
        //Set<String> keySet = map.keySet();
        for (String key :map.keySet()) {
            System.out.println(key+"----"+map.get(key));
            /*---------------keySet()-------------------
                    usa----美国
                    uk----英国
                    cn----zhongguo*/
        }
        //3.2使用entrySet()方法
        System.out.println("-----------entrySet()--------------");
        //Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for (Map.Entry<String, String> entry:map.entrySet()) {
            System.out.println(entry.getKey()+"--------"+entry.getValue());
         /*   -----------entrySet()--------------
            usa--------美国
            uk--------英国
            cn--------zhongguo*/
        }
        //4判断
        System.out.println(map.containsKey("cn"));
        System.out.println(map.containsValue("泰国"));

    }
}

Map集合的实现类

  • HashMap【重点】:
    • JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value。
  • Hashtable:
    • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
  • Properties:
    • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
  • TreeMap:
    • 实现了SortedMap接口(是Map的子接口),可以对key自动排序。

HashMap的使用

Students.java

package com.aggregation.demo04;

import java.util.Objects;

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

    public Student() {
    }

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

    public Student(String name, int stuNo) {
        this.name = name;
        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 instanceof Student)) return false;
        Student student = (Student) o;
        return getStuNo() == student.getStuNo() && Objects.equals(getName(), student.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getStuNo());
    }
}

Demo02.java

package com.aggregation.demo04;

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

/**
 * HashMap集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 使用key得hashcode和equals作为重复依据
 * author 大白很白
 */
public class Demo02 {
    public static void main(String[] args){
        //刚创建hashmap之后没有添加元素table==null  size=0 目的:节省空间
        //创建集合
        HashMap<Student, String> students = new HashMap<>();
        //1添加元素
        Student s1 = new Student("小红",1);
        Student s2 = new Student("小绿",2);
        Student s3 = new Student("小黑",3);
        students.put(s1,"地球");
        students.put(s2,"火星");
        students.put(s3,"水星");
        //students.put(s3,"金星");
        students.put(new Student("小红",1),"黑洞");
        System.out.println("元素个数:"+students.size());
        System.out.println(students.toString());
        //2删除
//        students.remove(s1);
//        System.out.println("删除之后:"+students.size());
//        System.out.println(students.toString());
        //3遍历
        //3.1使用keySet();
        System.out.println("------------keySet()------------------");
        for (Student key:students.keySet()) {
            System.out.println(key.toString()+"---------"+students.get(key));
        }
        //3.2使用entrySet();
        System.out.println("-------------entrySet()-------------");
        for (Map.Entry<Student, String> entry : students.entrySet()){
            System.out.println(entry.getKey()+"----------"+entry.getValue());
        }
        //4判断
        System.out.println(students.containsKey(s1));
        System.out.println(students.containsValue("宇宙"));

    }
}

HashMap源码分析

1 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //hashMap初始容量大小
2 static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
3 static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
4 static final int TREEIFY_THRESHOLD = 8;//jdk1.8当链表长度大于8时,调整成红黑树
5 static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度小于6时,调整成链表
6 static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树
7 transient Node<K,V>[] table;//哈希表中的数组
8 size;//元素个数

无参构造

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以后是尾插入

TreeMap的使用

需实现Comparable接口,或者使用定制比较comparator

Student.java

package com.aggregation.demo04;

import java.util.Objects;

public class Student implements Comparable<Student>{
    @Override
    public int compareTo(Student o) {
        //int n1=this.name.compareTo(o.getName());
        int n2=this.stuNo-o.getStuNo();
        return n2;
    }

    private String name;
    private int stuNo;

    public Student() {
    }

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

    public Student(String name, int stuNo) {
        this.name = name;
        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 instanceof Student)) return false;
        Student student = (Student) o;
        return getStuNo() == student.getStuNo() && Objects.equals(getName(), student.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getStuNo());
    }
}

Demo03.java

package com.aggregation.demo04;

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

/**
 * TreeMap的使用
 * 存储结构:红黑树
 * author 大白很白
 */
public class Demo03 {
    public static void main(String[] args) {
        //新建集合 或用定制比较 comparator
        TreeMap<Student, String> treeMap = new TreeMap<>();
        //1添加元素
        Student s1 = new Student("小红",1);
        Student s2 = new Student("小绿",2);
        Student s3 = new Student("小黑",3);
        treeMap.put(s1,"成都");
        treeMap.put(s2,"广州");
        treeMap.put(s3,"上海");
        treeMap.put(new Student("小黑",3),"北京");//值覆盖
        System.out.println("元素个数:"+treeMap.size());
        System.out.println(treeMap.toString());
        //2删除
        //treeMap.remove(s3);
        //treeMap.remove(new Student("小红",1));
        //System.out.println("删除之后:"+treeMap.size());
        //3遍历
        //3.1使用keySet()
        System.out.println("-----------使用keySet()---------");
        for (Student key:treeMap.keySet()) {
            System.out.println(key+"-----"+treeMap.get(key));
        }
        //3.2使用entrySet()
        System.out.println("-------------使用entrySet()-----------");
        for (Map.Entry<Student, String>entry:treeMap.entrySet()) {
            System.out.println(entry.getKey()+"-----"+entry.getValue());
            
        }
        //判断
        System.out.println(treeMap.containsKey(new Student("小黑",3)));


    }
}

Collections工具类

  • 概念:集合工具类,定义了除了存取以外的集合常用方法。

  • 方法:

    • public static void reverse(List<?> list) //反转集合中元素的顺序

    • public static void shuffle(List<?> list) //随机重置集合元素的顺序

    • public static void sort(List list) //升序排序(元素类型必须实现Comparable接口)

Demo04.java

package com.aggregation.demo04;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 演示Collections工具类的使用
 * @author 大白很白
 */
public class Demo04 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(15);
        list.add(17);
        list.add(2);
        list.add(8);
        list.add(10);
        //sort排序
        System.out.println("排序之前:"+list.toString());
        Collections.sort(list);
        System.out.println("排序之后:"+list.toString());
//        排序之前:[20, 15, 17, 2, 8, 10]
//        排序之后:[2, 8, 10, 15, 17, 20]

        //binarySearch二分查找
        int i = Collections.binarySearch(list, 15);
        System.out.println(i);//3,找到>=0;没找到,负数

        //copy复制
        List<Integer> dest = new ArrayList<>();//长度不同,需注意
        for (int j = 0; j < list.size(); j++) {
            dest.add(0);
        }
        Collections.copy(dest,list);
        System.out.println(dest.toString());//[2, 8, 10, 15, 17, 20]

        //reverse反转
        Collections.reverse(list);
        System.out.println("反转之后:"+list);//反转之后:[20, 17, 15, 10, 8, 2]

        //shuffle 打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:"+list);//打乱之后:[8, 2, 10, 17, 15, 20]

        //补充: list转成数组
        System.out.println("--------list转成数组-----------");
        Integer[] arr = list.toArray(new Integer[7]);
        System.out.println(arr.length);//7
        System.out.println(Arrays.toString(arr));//[15, 20, 8, 2, 17, 10, null]

        //数组转成集合
        System.out.println("----------数组转成集合---------");
        String[] names={"张三","李四","王武"};
        //集合是一个受限集合,不能添加和删除
        List<String> list2 = Arrays.asList(names);
        //list2.add("赵六");
        //list2.remove(0);
        System.out.println(list2);
        //把基本类型数组转成集合时,需要修改为包装类
        Integer[] nums = {100,200,300,400,500};
        List<Integer> list3 = Arrays.asList(nums);
        System.out.println(list3);//[100, 200, 300, 400, 500]
    }
}

集合总结

  • 集合的概念:
    • 对象的容器,和数组类似,定义了多个对象进行操作的常用方法。
  • List集合:
    • 有序、有下标、元素可以重复。(ArrayList、LinkedList、Vector)
  • Set集合
    • 无序、无下标、元素不可重复。(HashSet、TreeSet)
  • Map集合:
    • 存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable、TreeMap)
  • Collections:
    • 集合工具类,定义了除了存取以外的集合常用方法。
posted @ 2022-05-08 15:03  大白很白  阅读(32)  评论(0)    收藏  举报