JavaSE之集合框架

1、集合的概念

2、Collection接口

3、List接口与实现类

4、泛型和工具类

5、Set接口与实现类

6、Map接口与实现类

集合的概念

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

Collection体系集合

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

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()//将此集合转换成数组
  • 迭代器Iterator

    • hasNext();有没有下一个元素
    • Next();获取下一个元素
    • remove();删除当前元素
  • Collection的使用1

    • package com.collection;
      
      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.Iterator;
      
      /**
       * Collection接口使用说明
       * (1)添加元素
       * (2)删除元素
       * (3)遍历元素
       * (4)判断
       * @author A_sh
       * */
      public class Demo01 {
          public static void main(String args[]){
              //创建集合
              Collection collection = new ArrayList();
              //(1)添加元素
              collection.add("苹果");
              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 o: collection) {
                  System.out.println(o);
              }
              /*3.2使用迭代器(迭代器专门用来遍历集合的一种方式)*/
              //hasNext();有没有下一个元素
              //next();获取下一个元素
              //remove();删除当前元素
              System.out.println("----------------3.2使用迭代器---------------");
              Iterator it = collection.iterator();
              while(it.hasNext()){
                  String s = (String)it.next();
                  System.out.println(s);
                  //collection.remove(s);/*java.util.ConcurrentModificationException并发修改异常*/
                  /*it.remove();*///Iterator中的remove();函数删除
              }
              System.out.println("元素个数:"+collection.size());
              //(4)判断
              System.out.println("----------------判断---------------");
              System.out.println(collection.contains("西瓜"));
              System.out.println(collection.contains("葡萄"));
              System.out.println(collection.isEmpty());
          }
      }
      
  • Collection的使用2

    • package com.collection;
      
      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.Iterator;
      
      public class Demo02 {
          public static void main(String[] args){
              //新建Collection对象
              Collection collection = new ArrayList();
              Student s1 = new Student("曾阿牛",17);
              Student s2 = new Student("张无忌",18);
              Student s3 = new Student("张三丰",100);
              //1、添加数据
              collection.add(s1);
              collection.add(s2);
              collection.add(s3);
      
              System.out.println("元素个数:"+collection.size());
              System.out.println(collection.toString());
              //2、删除
              //collection.remove(s3);
              /*collection.remove(new Student("王重阳",99));*/
              /*collection.clear();*///清除集合
              System.out.println("删除之后:"+collection.size());
      
              //3、遍历
              //3.1、增强for
              System.out.println("-------------3.1使用增强for循环-------------");
              for (Object o:
                   collection) {
                  Student s = (Student) o;
                  System.out.println(o.toString());
              }
              //3.2、迭代器hasNext();next();remove();迭代过程中不能使用collection的删除方法
              System.out.println("----------------3.2使用迭代器---------------");
              Iterator it = collection.iterator();
              while(it.hasNext()){
                  Student s = (Student)it.next();
                  System.out.println(s.toString());
              }
              //4、判断
              System.out.println("----------------判断---------------");
              System.out.println(collection.contains(s1));
              System.out.println(collection.isEmpty());
          }
      }
      

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之间的集合元素。
  • List接口使用1:

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

    • package com.collection;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public class Demo04 {
          public static void main(String[] args){
              //创建集合
              List list = new ArrayList();
              //1添加数字数据(自动装箱)
              list.add(0);
              list.add(1);
              list.add(2);
              list.add(3);
              list.add(4);
              //隐藏有自动装箱,此时的数据已经是装箱后的数据
              System.out.println("元素个数:"+list.size());
              System.out.println(list.toString());
              //2删除操作
              /*list.remove(0);//传入脚标*/
              /*list.remove((Object) 3);//删除元素:3*/
              list.remove(new Integer(3));//删除元素3
              System.out.println("删除元素:"+list.size());
              System.out.println(list.toString());
      
              //3补充方法subList,返回子集合,含头不含尾
              List subList = list.subList(1,3);
              System.out.println(subList.toString());
      
          }
      }
      

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

ArrayList的使用

package com.collection;

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

public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        ArrayList arrayList = new ArrayList<>();
        //1添加元素
        Student s1 = new Student("刘德华",48);
        Student s2 = new Student("郭富城",59);
        Student s3 = new Student("梁朝伟",50);
        Student s4 = new Student("周星驰",48);

        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s4);
        System.out.println("元素个数:"+arrayList.size());
        System.out.println(arrayList.toString());

        //2删除元素
        arrayList.remove(new Student("刘德华",48));//此处Student类中重写equals方法(修改比较规则)后,可实现删除元素
        System.out.println("删除之后:"+arrayList.size());
        System.out.println(arrayList.toString());
        //3遍历元素【重点】
        //3.1使用迭代器
        System.out.println("-------------3.1使用迭代器----------");
        Iterator it = arrayList.iterator();
        while(it.hasNext()){
            Student s = (Student) it.next();
            System.out.println(s.toString());
        }
        //3.2列表迭代器
        System.out.println("-------------3.1列表迭代器----------");
        ListIterator its = arrayList.listIterator();
        while(its.hasNext()){
            Student s = (Student)its.next();
            System.out.println(s.toString());
        }
        //4判断
        System.out.println(arrayList.contains(new Student("梁朝伟",50)));
        System.out.println(arrayList.isEmpty());
        //5查找
        System.out.println(arrayList.indexOf(new Student("梁朝伟",50)));
    }
}

**【重点】**重写Student类的equals方法:

package com.collection;

import java.util.Objects;

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 o) {
        //1、判断是否同一对象
        if (this == o) return true;
        //2、判断是否Student类型
        if (!(o instanceof Student)) return false;
        //3、比较属性
        Student student = (Student) o;
        return age == student.age &&
                name.equals(student.name);
    }

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

*ArrayList源码分析

  1. DEFAULT_CAPACITY 默认容量,【注意】如果没有向集合中添加元素,默认容量为0
  2. elementData 存放元素的数组
  3. size 实际元素个数
  4. 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) {
            //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);//扩容,此时minCapacity为10
    }
	private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//每次扩容是原来的1.5倍
        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);//初次扩容为10
    }

Arrays.copyOf()源码:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
/**
这段代码定义了一个静态方法copyOf,用于创建一个新的数组,该数组是原始数组的副本,并具有指定的新长度和新类型。
方法的参数说明如下:
    <T,U>:泛型类型参数,T表示返回数组中元素的类型,U表示原始数组中元素的类型。
    original:要被复制的原始数组。
    newLength:新数组的长度。
    newType:新数组的类型。
方法的主要逻辑如下:
    1、使用SuppressWarnings("unchecked")抑制未检查的类型转换警告。
    2、判断newType是否为Object[]类,如果是,则创建一个新的Object数组并强制转换为T[]类型;否则,使用Array.newInstance方法根据newType的组件类型创建一个新的数组并强制转换为T[]类型。
    3、使用System.arraycopy方法将原始数组中的元素复制到新数组中,复制的长度为原始数组长度和新长度中的较小值。
    4、返回新创建的数组副本。
*/

Vector的使用

  • 存储结构:数组
  • 使用枚举器【】遍历
package com.collection;

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

/***
 * 演示Vector集合的使用
 * 存储结构:数组
 * @author A_sh
 */
public class Demo06 {
    public static void main(String[] args) {
        Vector vector = new Vector<>();
        //1添加元素
        vector.add("草莓");
        vector.add("西瓜");
        vector.add("苹果");

        System.out.println("元素个数:"+vector.size());
        //2删除元素
        /*vector.remove(0);
        vector.remove("西瓜");
        System.out.println("元素个数:"+vector.size());
        vector.clear();
        System.out.println("元素个数:"+vector.size());*/
        //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补充
        System.out.println(vector.firstElement());
        System.out.println(vector.lastElement());
        System.out.println(vector.elementAt(0));
    }
}

LinkedList的使用

package com.collection;

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

public class Demo07 {
    public static void main(String args[]){
        //创建集合
        LinkedList linkedList = new LinkedList<>();
        //1添加元素
        Student s1 = new Student("成剑",25);
        Student s2 = new Student("洛开样",25);
        Student s3 = new Student("徐招招",29);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        System.out.println("元素个数:"+linkedList.size());
        System.out.println(linkedList.toString());
        //2删除元素
        /*linkedList.remove(0);
        linkedList.remove(new Student("罗开样",25));
        System.out.println("元素个数:"+linkedList.size());*/
        //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  o : linkedList){
            Student s = (Student) o;
            System.out.println(s);
        }
        //3.3迭代器
        System.out.println("-----------迭代器-----------");
        Iterator e = linkedList.iterator();
        while(e.hasNext()){
            Student student = (Student) e.next();
            System.out.println(student.toString());
        }
        //3.4列表迭代器
        System.out.println("---------列表迭代器---------");
        ListIterator llt = linkedList.listIterator();
        while(llt.hasNext()){
            Student student = (Student) llt.next();
            System.out.println(student.toString());
        }
        //4判断
        System.out.println("---------判断---------");
        System.out.println(linkedList.contains(new Student("徐招招",29)));
        System.out.println(linkedList.isEmpty());
        //5获取
        System.out.println("---------获取---------");
        System.out.println(linkedList.indexOf(s1));
    }
}

*LinkedList源码分析

元素:

​ transient int size = 0;

​ transient Node first;

​ transient Node last;

方法:add()

节点:Node

//节点
	private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            //prev:前一个指向
            //element:当前元素值
            //next:后一个指向
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
//add()
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
//linkLast()
	void linkLast(E e) {
        final Node<E> l = last;//last的指向赋给l
        final Node<E> newNode = new Node<>(l, e, null);//对newNode中三个元素传参
        last = newNode;//last指向newNode
        if (l == null)
            first = newNode;//当newNode为链表中第一个被添加进来的节点时,first指向newNode
        else
            l.next = newNode;//当newNode不是链表中第一个被添加进来的节点时,l.next指向它
        size++;
        modCount++;
    }

ArrayList和LinkList的区别:
ArrayList和Linklist的区别

泛型

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

泛型类&泛型接口&泛型方法

package com.collection;
/**
 * 泛型类
 * 语法:类名<T>
 *     T是类型占位符,表示一种引用类型,如果编写多个,使用逗号隔开
 * @author A_sh
 * */
public class MyGeneric<T> {
    //使用泛型T
    //1创建变量
    T t;
    //2泛型作为方法的参数
    public void show(T t){
        System.out.println(t);
    }
    //3泛型作为方法的返回值
    public T getT(){
        return t;
    }
}
package com.collection;
/**
 * 泛型接口
 * 语法:接口名<T>
 *     注意:不能创建泛型静态常量
 * @param <T>
 */

public interface MyInterface<T> {
    String name = "Zhangsan";
    T server(T t);
}
//接口实现类1
public class MyInterfaceImpl1 implements MyInterface<String>{

    @Override
    public String server(String s) {
        System.out.println(s);
        return s;
    }
}
//接口实现类2
public class MyInterfaceImpl2<T> implements MyInterface<T> {

    @Override
    public T server(T t) {
        System.out.println(t);
        return t;
    }
}
package com.collection;

/**
 * 泛型方法
 * 语法:<T>返回值类型
 */
public class MyGenericMethod {
    //泛型方法,静态与否均可
    public <T> T show (T t){
        System.out.println("泛型方法"+t);
        return t;
    }
}

main:

package com.collection;

public class TestGeneric {
    public static void main(String[] args){
        //使用泛型类创建对象
        //【注意】1、泛型只能使用引用类型;2、不同的泛型类型对象之间不能相互赋值
        MyGeneric<String> myGeneric1 = new MyGeneric<String>();
        myGeneric1.t = "Hello";
        myGeneric1.show("Hello,everyone");
        String string = myGeneric1.getT();
        System.out.println(string);

        MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
        myGeneric2.t = 100;
        myGeneric2.show(200);
        Integer integer = myGeneric2.getT();
        System.out.println(integer);
        //泛型接口实现类的使用
        MyInterfaceImpl1 impl1 = new MyInterfaceImpl1();
        impl1.server("chenjian");
        MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<Integer>();
        impl2.server(100);

        //泛型方法的使用
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        myGenericMethod.show("中国加油");
        myGenericMethod.show(100);
        myGenericMethod.show(3.14);
    }
}

泛型集合

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

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

public class Demo08 {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add("金言");
        arrayList.add("康德");
        arrayList.add("阿杉");
        arrayList.add(100);
        arrayList.add(200);
        /*for(Object object:arrayList){
            String string = (String)object;
            System.out.println(string);
            //java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
        }*/
        ArrayList<Student> arrayList1 = new ArrayList<>();
        Student s1 = new Student("金言",20);
        Student s2 = new Student("康德",20);
        Student s3 = new Student("阿杉",20);
        arrayList1.add(s1);
        arrayList1.add(s2);
        arrayList1.add(s3);

        Iterator<Student> it = arrayList1.iterator();
        while(it.hasNext()){
            Student s = it.next();
            System.out.println(s.toString());
        }
    }
}

Set子接口

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

Set实现类

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

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
 * Set接口的使用
 *特点:(1)无序、没有下标;(2)不能重复
 * @author A_sh
 */

public class Demo01 {
    public static void main(String[] args){
        //创建集合
        Set<String> set = new HashSet<>();
        //1添加元素
        //数据存放没有顺序
        set.add("苹果");
        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存储结构

存储结构:哈希表(组+链表+红黑树

*1)根据hashCode来计算保存的位置,如果位置为空,则直接保存;
*2)如果不为空,再执行equals()方法,如果equals()方法为true,则认为重复,否则,形成链表

Person类(重写equals()和hashCode()方法)

package com.set;

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 instanceof Person)) return false;
        Person person = (Person) o;
        return age == person.age &&
                name.equals(person.name);
    }

    @Override
    public int hashCode() {
        //(1)31是质数,减少散列冲突;(2)31提高执行效率 ——> 31*i=(i<<5)-i
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
package com.set;

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

/**
 * Hashset的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * (1)根据hashCode来计算保存的位置,如果位置为空,则直接保存;
 * (2)如果不为空,再执行equals()方法,如果equals()方法为true,则认为重复,否则,形成链表
 */
public class Demo03 {
    public static void main(String[] args) {
        //创建集合
        HashSet<Person> persons = new HashSet<>();
        //1添加数据
        Person p1 = new Person("刘德华",20);
        Person p2 = new Person("郭富城",22);
        Person p3 = new Person("梁朝伟",23);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        //persons.add(p3);重复
        persons.add(new Person("梁朝伟",23));//重写equals()和hashCode()方法前,可行

        System.out.println("元素个数:"+persons.size());
        System.out.println(persons.toString());
        //2删除元素
        persons.remove(new Person("梁朝伟",23));//可删
        System.out.println("删除之后:"+persons.size());

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

    }
}

TreeSet的使用1:

package com.set;

import java.util.Objects;

public class Person implements Comparable<Person>{
    //实现Comparable接口
    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 instanceof Person)) return false;
        Person person = (Person) o;
        return age == person.age &&
                name.equals(person.name);
    }

    @Override
    public int hashCode() {
        //(1)31是质数,减少散列冲突;(2)31提高执行效率 ——> 31*i=(i<<5)-i
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    //重写compareTo接口,先按姓名比再按年龄比
    @Override
    public int compareTo(Person o) {
        int n1 = this.getName().compareTo(o.getName());
        int n2 = this.age-o.getAge();

        return n1==0? n2:n1;
    }
}java
package com.set;

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

/**
 * 使用TreeSet保存数据
 * 存储结构:红黑树
 * 要求:元素必须要实现Comarable接口
 */
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<Person> treeset = new TreeSet<>();
        //1添加元素
        Person p1 = new Person("xyz",20);
        Person p2 = new Person("abc",23);
        Person p3 = new Person("zs",24);
        Person p4 = new Person("zs",25);
        treeset.add(p1);
        treeset.add(p2);
        treeset.add(p3);
        treeset.add(p4);
        System.out.println("元素个数"+treeset.size());
        System.out.println(treeset.toString());
        //2删除
        treeset.remove(p1);
        System.out.println("元素个数"+treeset.size());
        //3遍历
        //3.1使用增强for
        System.out.println("-------------------");
        for (Person person:
             treeset) {
            System.out.println(person.toString());
        }
        //3.2使用迭代器
        System.out.println("-------------------");
        Iterator<Person> it = treeset.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //4判断
        System.out.println(treeset.contains(new Person("zs",24)));
    }
}

TreeSet的使用2:

package com.set;
import java.util.Comparator;
import java.util.TreeSet;
/**
 * TreeSet集合的使用
 * Comparable:可比较的
 * Comparator:实现定制比较(比较器)
 */
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("xzy",20);
        Person p2 = new Person("abc",22);
        Person p3 = new Person("wasd",25);
        Person p4 = new Person("chenj",25);

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

}

Map集合

Map(Interface)<——HashMap(Class)

Map(Interface)<——SortedMap(interface)<——TreeMap(class)

Map父接口

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

  • 方法:

    • V put(K key,V value)//将对象存入集合中,关联键值。key重复则覆盖原值。
    • Object get(Object key)//根据键获取对应的值。
    • Set keySet()//返回所有key。
    • Collection values()//返回包含所有值的Collection集合。
    • Set<Map.Entry<K,V>> entrySet()//键值匹配的Set集合。

Map接口的使用,示例1:

package com.map.demo01;

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

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

        map.put("cn","中华人民共和国");//覆盖

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

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

        map.put("usa","美国");
        //3遍历
        //3.1使用keySet()
        System.out.println("------使用keySet()---------");
        Set<String> keyset = map.keySet();
        for(String key : keyset){
            System.out.println(key+"--------"+map.get(key));
        }
        //3.2使用entrySet()
        Set<Map.Entry<String,String>> entries = map.entrySet();
        for(Map.Entry<String,String> entry : entries){
            System.out.println("key:"+entry.getKey()+" value:"+entry.getValue());
        }
        //4判断
        System.out.println(map.containsKey("cn"));
        System.out.println(map.containsValue("德国"));
    }
}

HashMap的使用:

Student类重写方法:hashcode()和equals()

package com.map.demo01;

import java.util.Objects;

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

    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 instanceof Student)) 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.map.demo01;

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

/**
 * HashMap集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 *使用key,hashcode()和equals()作为重复
 */
public class Demo02 {
    public static void main(String[] args){
        HashMap<Student,String> students = new HashMap<Student,String>();
        //1添加元素
        Student s1 = new Student("孙悟空",500);
        Student s2 = new Student("猪八戒",300);
        Student s3 = new Student("沙和尚",200);
        students.put(s1,"北京");
        students.put(s2,"上海");
        students.put(s3,"天津");
        students.put(s3,"南京");
        students.put(new Student("沙和尚",200),"杭州");//添加成功
        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()方法
        for(Student key : students.keySet()){
            System.out.println(key+"==========="+students.get(key));
        }
        //3.2entrySet()方法
        for(Map.Entry<Student,String> entry : students.entrySet()){
            System.out.println(entry.getKey()+"==========="+entry.getValue());
        }
        //4判断
        System.out.println(students.containsKey(s2));
        System.out.println(students.containsValue("上海"));
    }
}

HashMap源码分析

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16,hashMap初始容量大小
static final int MAXIMUM_CAPACITY = 1 << 30;//hashMapd数组最大容量
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;//元素个数
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);
}

总结:

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

Map集合的实现类

  • HashMap【重点】:

    • jdk1.2版本,线程不安全,运行效率快;允许用null作为key或value
  • Hashtable

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

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

TreeMap的使用

  • 存储结构为红黑树

  • 使用toString()方法时,需要重写CompareTo()方法

package com.map.demo01;

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

/**
 * TreeMap的使用
 * 存储结构:红黑树
 */
public class Demo03 {
    public static void main(String[] args){
        //新建集合
        TreeMap<Student,String> treeMap = new TreeMap<Student,String>();
        //1添加元素
        Student s1 = new Student("孙悟空",500);
        Student s2 = new Student("猪八戒",300);
        Student s3 = new Student("沙和尚",200);
        treeMap.put(s1,"北京");
        treeMap.put(s2,"上海");
        treeMap.put(s3,"天津");
        treeMap.put(s3,"南京");
        System.out.println("元素个数:"+treeMap.size());
        System.out.println(treeMap.toString());
        //报错ClassCastException,
        // 由于红黑树的数据结构和Student类型目前无法完成比较,需要重写CompareTo()方法
        //2删除元素
        treeMap.remove(s1);
        System.out.println(treeMap.size());
        System.out.println(treeMap.toString());
        //3遍历
        //3.1使用keySet()方法
        for(Student key : treeMap.keySet()){
            System.out.println(key+"==========="+treeMap.get(key));
        }
        //3.2entrySet()方法
        for(Map.Entry<Student,String> entry : treeMap.entrySet()){
            System.out.println(entry.getKey()+"==========="+entry.getValue());
        }
        //4判断
        System.out.println(treeMap.containsKey(s2));
        System.out.println(treeMap.containsValue("上海"));
    }
}

Collections工具类

package com.map.demo01;

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

/**
 * Collections工具类的使用
 *
 */
public class Demo04 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(2);
        list.add(5);
        list.add(12);
        list.add(30);
        list.add(6);
        //sort排序
        System.out.println("排序之前:"+list.toString());
        Collections.sort(list);//排序工具
        System.out.println("排序之后:"+list.toString());

        //binarySearch
        int i = Collections.binarySearch(list,12);
        System.out.println(i);

        //copy复制
        List<Integer> dest = new ArrayList<>();
        for(int j = 0 ;  j<list.size() ; j++){
            dest.add(0);
        }
        Collections.copy(dest,list);//java.lang.IndexOutOfBoundsException: Source does not fit in dest
        // dest需要提前设置链表长度和元素初始化
        System.out.println(dest.toString());

        //reverese反转
        Collections.reverse(list);
        System.out.println("反转之后:" +list.toString());
        //shuffle打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:" +list.toString());

        //补充:list转成数组
        System.out.println("--------list转成数组------------");
        Integer[] arr = list.toArray(new Integer[0]);
        System.out.println(arr.length);
        System.out.println(Arrays.toString(arr));
        //数组转成集合
        String[] names = {"张三","李四","王五"};
        List<String> list2 = Arrays.asList(names);
        //此集合为受限集合,不能添加和删除元素
        //把基本类型转为引用类型时,需要修改为包装类
        System.out.println(list2);
        Integer[] nums = {100,20,200,30,230};
        List<Integer> list3 = Arrays.asList(nums);
        System.out.println(list3);

    }
}

总结

  • 集合的概念:
    • 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法。
  • List集合:
    • 有序、有下标,元素可重复。(ArrayList、LinkedList、Vector)
  • Set集合:
    • 无序,无下标、元素不可重复。(HashSet、TreeSet)
  • Map集合:
    • 存储一对数据,无序、无下标、键不可重复,值可重复。(HashMap、HashTable、TreeMap)
  • Collections:
    • 集合工具类,定义了除了存取以外的集合常用方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值