一给 发表于 2024-12-19 17:30:52

Java集合(完整版)

集合框架

Collection集合

概念:对象的容器,界说了对多个对象进行操作的常用方法。可以实现数组的功能
和数组的区别:


[*]数组的长度固定,集合长度不固定
[*]数组可以存储基本范例和引用范例,集合只能存储引用范例
Collection体系集合

如图所示:
https://i-blog.csdnimg.cn/direct/ae5a51c5a87e47978edd7a773db9a6c5.jpeg#pic_center
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.collection.Demo01;

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

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());// 添加之后的元素个数:3
      System.out.println(collection);// [苹果, 西瓜, 榴莲]
      // 2. 删除元素
      // collection.remove("榴莲");
      // collection.remove("西瓜");
      // System.out.println("删除之后剩余的元素个数:"+ collection.size());// 删除之后剩余的元素个数:1
       // 2.1 清空元素
//      collection.clear();
//      System.out.println("清空元素剩余:" + collection.size());// 清空元素剩余:0

      // 3. 遍历元素
      // 3.1 使用增强for
      System.out.println("----------3.1 使用增强for-------------");
      for (Object obj:collection
             ) {
            System.out.println(obj);
      }
      /*
      ----------3.1 使用增强for-------------
      苹果
      西瓜
      榴莲
         */
      // 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删除方法
            // collection.remove(s);// ConcurrentModificationException   并发修改异常
            // it.remove();   // 迭代器提供的方法
      }
      System.out.println("剩余的元素个数: "+ collection.size());
      /*
      ----------3.2 使用迭代器-------------
      苹果
      西瓜
      榴莲
      剩余的元素个数: 3
         */
      // 4. 判断
      System.out.println(collection.contains("xigua"));// false
      System.out.println(collection.contains("西瓜"));// true
      System.out.println(collection.isEmpty());// false   判断是否为空// null空 为 true ; not null非空 为 false

    }


}

下面是保存学生信息的代码实现:
学生类 Student:
package com.collection.Demo01;

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

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

    public Student() {

    }

    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 "学生信息:";
    }

    @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;
            // 4 比较属性
            if (this.name.equals(s.getName())&&this.age==s.getAge()){
                return true;
            }
      }
      // 5 不满足条件返回false
      return false;
    }
}
代码验证:
package com.collection.Demo01;

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("张三",18);
      Student s2 = new Student("李四",17);
      Student s3 = new Student("王五",19);
      // 1. 添加数据
      collection.add(s1);
      collection.add(s2);
      collection.add(s3);
      System.out.println("元素个数:" + collection.size());// 元素个数:3
      System.out.println(collection);// [学生信息:, 学生信息:, 学生信息:]
      // 2. 删除数据
      // collection.remove(s2);
      // collection.remove(new Student("王五",19));// 并没有删除
      // collection.clear();
      // System.out.println("删除之后的剩余元素:" + collection.size());// 删除之后的剩余元素:0    // 只是删掉了地址


      // 3. 遍历

      // 3.1 增强for
      System.out.println("--------增强for------");
      for (Object obj:collection) {
                Student s = (Student) obj;
            System.out.println(s.toString());
      }
      /*
      --------增强for------
      学生信息:
      学生信息:
      学生信息:
         */

      // 3.2 迭代器
      // hasNext();   next();   remove();   迭代过程中不能使用collection的删除方法
      System.out.println("--------迭代器------");
      Iterator it = collection.iterator();
      while (it.hasNext()){
            Student s = (Student)it.next();
            System.out.println(s);
      }
      /*
      --------迭代器------
      学生信息:
      学生信息:
      学生信息:
         */

      // 4. 判断
      System.out.println(collection.contains(s1));// true
      System.out.println(collection.isEmpty());// false

    }
}
List子接口

特点:有序,有下标,元素可以重复
方法:


[*]void add (int index,Object o) // 在index位置插入对象
[*]boolean addAll (int index,Collection c) 将一个集合中的元素添加到此集合中的index 位置
[*]Object get (int index) // 返回集合中指定位置的元素
[*]List subList (int fromIndex,int toIndex) // 返回fromIndex和toIndex之间的集合元素
下面是字符串案例:
package com.collection.list;

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

public class Demo01 {
    public static void main(String[] args) {
      // 先创建集合对象
      List list = new ArrayList();
      // 1. 添加元素

      list.add("小米");
      list.add("华为");
      list.add(0,"苹果");
      System.out.println("元素个数:" + list.size());// 元素个数:3
      System.out.println(list.toString());// [苹果, 小米, 华为]
      // 2. 删除元素
      // list.remove("华为");
      // list.remove(1);
      // System.out.println("删除之后还剩余:" + list.size());// 删除之后还剩余:1
      // System.out.println(list);// [苹果]
      // 3. 遍历
      // 3.1 使用for遍历
      System.out.println("--------使用for遍历--------");
      for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
      }
      /*
      --------使用for遍历--------
      苹果
      小米
      华为
         */
      // 3.2 使用增强for
      System.out.println("--------使用增强for--------");
      for (Object obj:list
             ) {
            System.out.println(obj);
      }
      /*
      --------使用增强for--------
      苹果
      小米
      华为
         */
      // 3.3 使用迭代器
      Iterator it = list.iterator();
      System.out.println("--------使用迭代器--------");
      while (it.hasNext()){
            System.out.println(it.next());
      }
      /*
      --------使用迭代器--------
      苹果
      小米
      华为
         */
      // 3.4 使用列表迭代器,和Iterator的区别: ListIterator可以向前或者向后遍历,添加,删除,修改元素
      ListIterator lit = list.listIterator();
      System.out.println("--------使用列表迭代器==从前往后--------");
      while(lit.hasNext()){
            System.out.println(lit.nextIndex()+":" +lit.next());
      }
      /*
      --------使用列表迭代器==从前往后--------
      0:苹果
      1:小米
      2:华为
         */
      System.out.println("--------使用列表迭代器==从后往前--------");
      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
      System.out.println(list.indexOf("华为"));// 2
    }
}
下面是数字,基本范例(自动装箱):
package com.collection.list;

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

public class Demo02 {
    public static void main(String[] args) {
      // 创建集合
      List list = new ArrayList();
      // 1. 添加数字数据(自动装箱)
      list.add(10);
      list.add(20);
      list.add(30);
      list.add(40);
      list.add(50);
      System.out.println("元素个数:"+list.size());// 元素个数:5
      System.out.println(list);//
      // 2. 删除操作
      // list.remove(2);
      // list.remove(new Integer(20));
      // list.remove((Object) 40);
      // System.out.println("删除元素:" + list.size());// 删除元素:2
      // System.out.println(list);//
      // 3. 补充方法:subList返回子集合,左闭右开区间[ )
      List subList = list.subList(1,4);
      System.out.println(subList);//


    }
}

下面是学生信息:
学生类同上:
package com.collection.list;

import com.collection.Demo01.Student;

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

public class Demo03 {
    public static void main(String[] args) {
      // 创建集合
      ArrayList arrayList = new ArrayList();
      // 1. 添加元素
      Student s1 = new Student("源氏",18);
      Student s2 = new Student("艾什",18);
      Student s3 = new Student("狂鼠",19);
      arrayList.add(s1);
      arrayList.add(s2);
      arrayList.add(s3);
      System.out.println("元素个数:"+arrayList.size());// 元素个数:3
      System.out.println(arrayList);// [学生信息:, 学生信息:, 学生信息:]
      // 2. 删除元素
      // arrayList.remove(new Student("狂鼠",19));// equals(this==obj)
      // arrayList.remove(s2);
      // System.out.println("删除之后:" + arrayList.size());// 删除之后:1
      // System.out.println(arrayList);// [学生信息:]
      // 3. 遍历元素⭐
      // 使用迭代器
      System.out.println("----------使用迭代器----------");
      Iterator it = arrayList.iterator();
      while (it.hasNext()){
            Student s = (Student) it.next();
            System.out.println(s.toString());
      }
      /*
      ----------使用迭代器----------
      学生信息:
      学生信息:
      学生信息:
         */
      // 使用列表迭代器
      ListIterator lit = arrayList.listIterator();
      System.out.println("----------使用列表迭代器==顺序----------");
      while (lit.hasNext()){
            Student s = (Student) lit.next();
            System.out.println(s.toString());
      }
      /*
      ----------使用列表迭代器==顺序----------
      学生信息:
      学生信息:
      学生信息:
         */
      System.out.println("----------使用列表迭代器==逆序----------");
      while (lit.hasPrevious()){
            Student s = (Student) lit.previous();
            System.out.println(s.toString());
      }
      /*
      ----------使用列表迭代器==逆序----------
      学生信息:
      学生信息:
      学生信息:
         */
      // 4. 判断
      System.out.println(arrayList.contains(new Student("狂鼠",19)));// true
      System.out.println(arrayList.contains(s2));// true
      System.out.println(arrayList.isEmpty());// false
      // 5. 查找
      System.out.println(arrayList.indexOf(new Student("狂鼠",19)));// 2
      System.out.println(arrayList.indexOf(new Student("源氏",19)));// -1// 年龄应为18 ,没有查找到返回-1



    }
}
List 实现类



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

源码分析:
DEFAULT_CAPACITY = 10 ; 默认容量
​ 留意:如果没有向集合中添加任何元素时,容量为0;
​ 添加一个元素之后,容量为10;
​ 每次扩容的巨细是原来的1.5倍
elementDate 存放元素的数组
size 实际元素个数
add () 添加元素
Vector

Vector简介
Vector 是矢量队列,它是JDK1.0版本添加的类。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。
Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能。
Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。
和ArrayList不同,Vector中的操作是线程安全的。
(01) Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若利用默认构造函数,则Vector的默认容量巨细是10。
(02) 当Vector容量不敷以容纳全部元素时,Vector的容量会增长。若容量增长系数 >0,则将容量的值增长“容量增长系数”;否则,将容量巨细增长一倍。
(03) Vector的克隆函数,便是将全部元素克隆到一个数组中。
package com.collection.vector;

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

public class Demo01 {

    public static void main(String[] args) {
      // 创建集合
      Vector vector = new Vector();
      // 1. 添加元素
      vector.add("苹果");
      vector.add("草莓");
      vector.add("葡萄");
      System.out.println("元素个数:"+vector.size());// 元素个数:3
      System.out.println(vector);// [苹果, 草莓, 葡萄]
      // 2. 删除元素
      // vector.remove(0);
      // vector.remove("葡萄");
      // vector.clear();
      // System.out.println("元素个数:" + vector.size());// 元素个数:0
      // 3. 遍历
      // 使用枚举器
      Enumeration en = vector.elements();
      while (en.hasMoreElements()){
            String str = (String)en.nextElement();
            System.out.println(str);
      }
      /*
      苹果
      草莓
      葡萄
         */
      // 4. 判断
      System.out.println(vector.contains("葡萄"));// true
      System.out.println(vector.isEmpty());// false
      // 5. 其他方法
      System.out.println(vector.firstElement());// 苹果
      System.out.println(vector.lastElement());// 葡萄
      System.out.println(vector.elementAt(1));// 草莓
    }
}

LinkedList

LinkedList官方文档
LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,而是存储在单独的节点中,然后通过引用将节点连接起来了,因此在恣意位置插入大概删除元素时,不需要搬移元素,效率比较高。
留意:
LinkedList实现了List接口
LinkedList的底层利用了双向链表
LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
LinkedList的恣意位置插入和删除元素时效率比较高,时间复杂度为O(1)
LinkedList比较适合恣意位置插入的场景
package com.collection.vector;

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

public class Demo01 {

    public static void main(String[] args) {
      // 创建集合
      Vector vector = new Vector();
      // 1. 添加元素
      vector.add("苹果");
      vector.add("草莓");
      vector.add("葡萄");
      System.out.println("元素个数:"+vector.size());// 元素个数:3
      System.out.println(vector);// [苹果, 草莓, 葡萄]
      // 2. 删除元素
      // vector.remove(0);
      // vector.remove("葡萄");
      // vector.clear();
      // System.out.println("元素个数:" + vector.size());// 元素个数:0
      // 3. 遍历
      // 使用枚举器
      Enumeration en = vector.elements();
      while (en.hasMoreElements()){
            String str = (String)en.nextElement();
            System.out.println(str);
      }
      /*
      苹果
      草莓
      葡萄
         */
      // 4. 判断
      System.out.println(vector.contains("葡萄"));// true
      System.out.println(vector.isEmpty());// false
      // 5. 其他方法
      System.out.println(vector.firstElement());// 苹果
      System.out.println(vector.lastElement());// 葡萄
      System.out.println(vector.elementAt(1));// 草莓
    }
}

ArrayList和LinkedList的区别
ArrayList的物理存储空间是连续的,LinkedList物理上不一定连续。
ArrayList支持随机访问,LinkedList不支持随机访问。
ArrayList在插入和删除的时候时间复杂度O(N),LinkedList时间复杂度O(1);所以LinkedList适合频繁插入和删除的场景。
ArrayList空间不够需要动态扩容,LinkedList不需要。
泛型

Java泛型是JDK1.5中引入的一个新特性,其本质是参数化范例,把范例作为参数传递
常见形式有:泛型类、泛型接口、泛型方法
语法: T 称为范例占位符,表示一种引用范例
长处:1 提高代码的重(chong)用性
​ 2 防止范例转换异常,提高代码的安全性
下面是泛型类:
package com.collection.generic;

public class Generic<T> {
    // 泛型类:Generic<T>
    // 语法: 类名<T>
    // T是类型占位符,表示一种引用类型,如果编写多个使用逗号隔开

    // 使用泛型 T
    // 1. 创建变量
    // 泛型不能实例化
    T t ;

    // 2. 泛型作为方法的参数
    public void show(T t){
      System.out.println("泛型作为方法的参数:" + t);
    }

    // 3. 泛型作为方法的返回值
    public T getT(){
      // return (T)("泛型作为方法的返回值" + t);
         return t;
    }
}

下面是泛型方法:
package com.collection.generic;


/**
*
* 泛型方法
* 语法:<T>返回值类型
*
*/
public class GenericMethod {
    // 泛型方法
    public <T> T show(T t){
      System.out.println("泛型方法 "+ t);
      return t;
    }
}

下面是泛型接口:
接口
package com.collection.generic;

/**
* 泛型接口
* 语法:接口名<T>
* 注意:不能创建静态常量
* @param <T>
*/
public interface GenericService<T> {
    String name = "张三";

    T server(T t);
}
package com.collection.generic;

public class GenericServiceImpl implements GenericService<String>{

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

public class GenericServiceImpl2<T> implements GenericService<T>{

    @Override
    public T server(T t) {
      System.out.println(t);
      return t;
    }
}
泛型测试:
package com.collection.generic;

public class TestGeneric {
    public static void main(String[] args) {
      // 使用泛型类创建对象
      /*
      注意:
      1. 泛型只能使用引用类型
      2. 不同泛型类型对象之间不能相互赋值
         */
      Generic<String> generic = new Generic<String>();
      generic.t = "Java";
      generic.show("我爱学习Java,大家加油!");// 泛型作为方法的参数:我爱学习Java,大家加油!
      String string = generic.getT();
      System.out.println(string);// Java

      Generic<Integer> generic1 = new Generic<>();
      generic1.t = 18;
      generic1.show(180);// 泛型作为方法的参数:180
      Integer integer = generic1.getT();
      System.out.println(integer);// 18

      // 泛型接口
      GenericService gs = new GenericServiceImpl();
      gs.server("java");// java

      GenericService gs2 = new GenericServiceImpl2();
      gs2.server(10086);// 10086

      // 泛型方法
      GenericMethod gm = new GenericMethod();
      gm.show("java is best!");// 泛型方法 java is best!
      gm.show(10086);// 泛型方法 10086
      gm.show(3.1415926);// 泛型方法 3.1415926

    }
}
泛型集合
概念:参数化范例、范例安全的集合、逼迫集合元素的范例必须同等
特点:


[*]编译时即可查抄,而非运营时抛出异常
[*]访问时,不必范例转换(拆箱)
[*]不同泛型之间引用不能相互赋值,泛型不存在多态
Set子接口


[*] Set 接口是Collection的子接口,相当于数学上的集合
[*] 特点:

[*]不答应元素重复,添加雷同的元素,返回false
[*]无序,无下标。不会记载元素的先后添加顺序
[*]判断俩个元素是否相等用的是equals方法

[*] 方法:全部继承自Collection中的方法
Set实现类


[*]HashSet 是Set 最长用的接口,底层利用Hash(散列)算法,查询和插入速度较快
[*]HashSet 判断俩个对象是否相等,equals比较
[*]对象的HashCode值决定了在Hash表中的位置
[*]判断添加对象和集合元素对象HashCode值
[*]不等: 直接将新添加对象存储导对应位置
[*]相等: 再继承判断新对象和集合中对象的具体值:
[*]HashCode 雷同,equals true ,则是同一个对象,则不保存hashtable中
[*]HashCode 雷同,equals false,存储到同槽的链表上





[*]基于HashCode计算元素存放位置
[*]当存入元素的哈希码雷同时,会调用equals进行确认,如果为true 则拒绝后者存入
测试Set接口的利用:
package com.collection.set;

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

/**
*
* 测试Set接口的使用
* 特点:无序、无下标 且 不能重复
*
*/
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());// 元素个数: 3
      System.out.println(set.toString());// [苹果, 华为, 小米]// 是无序的

      // 2. 删除数据
      // set.remove("华为");
      // System.out.println(set);// [苹果, 小米]

      // 3. 遍历⭐
      // 3.1 使用增强for
      System.out.println("--------使用增强for---------");
      for (Object obj:set
             ) {
            System.out.println(obj);
      }
      /*
      --------使用增强for---------
      苹果
      华为
      小米
         */
      // 3.2 使用迭代器
      System.out.println("--------使用迭代器---------");
      Iterator<String> it = set.iterator();
      while (it.hasNext()){
            System.out.println(it.next());
      }
      /*
      --------使用迭代器---------
      苹果
      华为
      小米
         */
      // 4. 判断
      System.out.println(set.contains("苹果"));// true
      System.out.println(set.isEmpty());// false


    }
}

HashSet集合的利用 1 :
package com.collection.set;

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

/**
*
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
*/
public class Demo02 {
    public static void main(String[] args) {
      // 新建集合
      HashSet<String> hashSet = new HashSet<>();
      // 1. 添加元素
      hashSet.add("源氏");
      hashSet.add("闪光");
      hashSet.add("狂鼠");
      hashSet.add("艾什");
      hashSet.add("小美");
      // hashSet.add("小美");// 重复的不添加
      System.out.println("元素个数:"+hashSet.size());// 元素个数:5
      System.out.println(hashSet.toString());// [狂鼠, 源氏, 艾什, 小美, 闪光]
      // 2. 删除
      // hashSet.remove("源氏");
      // System.out.println(hashSet.toString());// [狂鼠, 艾什, 小美, 闪光]
      // hashSet.clear();
      // System.out.println(hashSet);// []
      // 3. 遍历
      // 3.1 使用增强for
      System.out.println("------使用增强for--------");
      for (String s:hashSet
             ) {
            System.out.println(s);
      }
      /*
      ------使用增强for--------
      狂鼠
      源氏
      艾什
      小美
      闪光
         */
      // 3.2 使用迭代器
      System.out.println("------使用迭代器--------");
      Iterator it = hashSet.iterator();
      while (it.hasNext()){
            System.out.println(it.next());
      }
      /*
      ------使用迭代器--------
      狂鼠
      源氏
      艾什
      小美
      闪光
         */
      // 4. 判断
      System.out.println(hashSet.contains("死神"));// false
      System.out.println(hashSet.contains("源氏"));// true
      System.out.println(hashSet.isEmpty());   // false

    }
}

HashSet集合的利用 2 :
package com.collection.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> people = new HashSet<>();
      // 1. 添加数据
      Person p1 = new Person("源氏",18);
      Person p2 = new Person("艾什",19);
      Person p3 = new Person("闪光",20);
      Person p4 = new Person("狂鼠",21);

      people.add(p1);
      people.add(p2);
      people.add(p3);
      people.add(p4);
      // people.add(p4);// 重复 不添加
      people.add(new Person("狂鼠",21));// 重写了hashcode方法与equals方法
      System.out.println("元素个数:"+ people.size());// 元素个数:4
      System.out.println(people.toString());//

      // 2. 删除
      // people.remove(p1);
      // people.remove(new Person("狂鼠",21));// 因为重写hashcode方法与equals方法,所以也可以
      // System.out.println("删除后:"+people.size());// 删除后:2
      // System.out.println(people);//

      // 3. 遍历⭐
      // 3.1 使用增强for
      System.out.println("------使用增强for--------");
      for (Person person:people
             ) {
            System.out.println(person.toString());
      }
      /*
      ------使用增强for--------
      Person{name='闪光', age=20}
      Person{name='艾什', age=19}
      Person{name='源氏', age=18}
      Person{name='狂鼠', age=21}
         */
      // 3.2 使用迭代器
      System.out.println("------使用迭代器--------");
      Iterator<Person> it = people.iterator();
      while (it.hasNext()){
            System.out.println(it.next());
      }
      /*
      ------使用迭代器--------
      Person{name='闪光', age=20}
      Person{name='艾什', age=19}
      Person{name='源氏', age=18}
      Person{name='狂鼠', age=21}
         */
      // 4. 判断
      System.out.println(people.contains(new Person("狂鼠",21)));// true
      System.out.println(people.contains(p2));// true
      System.out.println(people.isEmpty());// false

    }
}

Person类

package com.collection.set;

import java.util.Objects;

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

    public Person() {

    }

    public Person(String name, int age) {
      super();
      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 +
                '}';
    }

    // 快捷键 快速 重写equals 和 hashCode 方法
    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Person person = (Person) o;
      return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
      return Objects.hash(name, age);
    }
   
   
//    @Override
//    public boolean equals(Object o) {
//      if (this == o)
//      {
//            return true;
//      }
//      if (o == null ){
//            return false;
//      }
//      if (o instanceof Person){
//            Person p = (Person) o;
//            if (this.name.equals(p.getName())&&this.age==p.getAge()){
//                return true;
//            }
//      }
//      return false;
//    }
//
//    @Override
//    public int hashCode() {
//      int n1 = this.name.hashCode();
//      int n2 = this.age;
//      return n1+n2;
//    }

}
TreeSet



[*]基于排序顺序实现元素不重复
[*]实现了SortedSet接口,对集合元素自动排序
[*]元素对象的范例必须实现Comparable接口,指定排序规则
[*]通过CompareTo方法确定是否为重复元素
下面是TreeSet的利用
package com.collection.treeset;

import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet 的使用
* 存储结构:红黑树
*/
public class Demo01 {
    public static void main(String[] args) {
      // 创建集合
      TreeSet<String> treeSet = new TreeSet<>();
      // 1. 添加元素
      treeSet.add("xyz");
      treeSet.add("abc");
      treeSet.add("java");
      treeSet.add("c++");
      treeSet.add("java");// 元素重复不添加
      System.out.println("元素个数:"+treeSet.size());// 元素个数:4
      System.out.println(treeSet.toString());//
      // 2. 删除元素
//      treeSet.remove("java");
//      treeSet.remove("c++");
//      System.out.println("删除元素:"+ treeSet.size());// 删除元素:2
//      System.out.println(treeSet.toString());//
      // 3. 遍历
      // 3.1 使用增强for
      System.out.println("---------使用增强for--------");
      for (String s: treeSet) {
            System.out.println(s);
      }
      /*
      ---------使用增强for--------
      abc
      c++
      java
      xyz
         */
      // 3.2 使用迭代器
      System.out.println("---------使用迭代器--------");
      Iterator<String> it = treeSet.iterator();
      while (it.hasNext()){
            System.out.println(it.next());
      }
      /*
      ---------使用迭代器--------
      abc
      c++
      java
      xyz
         */
      // 4. 判断
      System.out.println(treeSet.contains("java"));// true
      System.out.println(treeSet.contains("php"));// false
      System.out.println(treeSet.isEmpty());// false
    }
}

利用TreeSet保存数据
package com.collection.treeset;

import com.collection.set.Person;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 使用TreeSet保存数据
* 要求:
*元素必须要实现Comparable接口,compareTo();方法返回值为0,认为是重复元素
*/
public class Demo02 {

    public static void main(String[] args) {
      // 创建集合
      TreeSet<Person> persons = new TreeSet<>();
      // 1. 添加元素
      Person p1 = new Person("java",18);
      Person p2 = new Person("php",19);
      Person p3 = new Person("c++",20);
      Person p4 = new Person("xyz",21);
      Person p5 = new Person("java",1970);
      persons.add(p1);
      persons.add(p2);
      persons.add(p3);
      persons.add(p4);
      persons.add(p5);
      System.out.println("元素个数:" + persons.size());// 元素个数:5
      System.out.println(persons);//
      // 2. 删除
//      persons.remove(p2);
//      persons.remove(new Person("xyz",21));
//      System.out.println("删除元素:"+persons.size());   // 删除元素:3
//      System.out.println(persons.toString());//

      // 3. 遍历
      // 3.1 使用增强for
      System.out.println("---------使用增强for--------");
      for (Person p: persons
             ) {
            System.out.println(p);
      }
      /*
      ---------使用增强for--------
      Person{name='c++', age=20}
      Person{name='java', age=18}
      Person{name='java', age=1970}
      Person{name='php', age=19}
      Person{name='xyz', age=21}
         */
      // 3.2 使用迭代器
      System.out.println("---------使用迭代器--------");
      Iterator<Person> it = persons.iterator();
      while (it.hasNext()){
            System.out.println(it.next());
      }
      /*
      ---------使用迭代器--------
      Person{name='c++', age=20}
      Person{name='java', age=18}
      Person{name='java', age=1970}
      Person{name='php', age=19}
      Person{name='xyz', age=21}
         */
      // 4. 判断
      System.out.println(persons.contains(p1));// true
      System.out.println(persons.contains(new Person("javase",1970)));// false
      System.out.println(persons.isEmpty());// false

    }
}




引用了Person类,重写 compareTo(); 方法
// 先按姓名比,然后再按年龄比
    @Override
    public int compareTo(Person o) {
      int n1 = this.getName().compareTo(o.getName());
      int n2 = this.age-o.getAge();
      returnn1==0?n2:n1;
    }
TreeSet集合的利用
package com.collection.treeset;

import com.collection.set.Person;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet 集合的使用
* Comparator : 实现比较定制 (他是一个比较器)
* Comparable : 可比较的
*/
public class Demo03 {
    // 创建集合
    public static void main(String[] args) {
      TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {// 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("java",24);
      Person p2 = new Person("php",26);
      Person p3 = new Person("c++",20);
      Person p4 = new Person("xyz",17);
      Person p5 = new Person("abc",17);
      persons.add(p1);
      persons.add(p2);
      persons.add(p3);
      persons.add(p4);
      persons.add(p5);
      System.out.println(persons);

    }
}


结果:
      
      先比较的age,再比较name
      添加p5之后 ,age相同,比较name
      
案例:
要求:利用TreeSet集合实现字符串按照长度进行排序
​ helloworld zhangsan lisi xian beijing nanjing haerbin
​ Comparator 接口实现定制比较
代码实现:
package com.collection.treeset;


import java.util.Comparator;
import java.util.TreeSet;
/**
* 案例:
* 要求:使用TreeSet集合实现字符串按照长度进行排序
* helloworld   zhangsan    lisi    xian    beijing   nanjing   haerbin
* Comparator 接口实现定制比较
*/
public class Demo04 {
    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("zhangsan");
      treeSet.add("lisi");
      treeSet.add("xian");
      treeSet.add("beijing");
      treeSet.add("nanjing");
      treeSet.add("haerbin");
      System.out.println(treeSet.toString());

    }
}

结果:
      先比较长度,长度相同,则比较name
      
Map集合

Map体系集合

https://i-blog.csdnimg.cn/direct/fb8a64361d0d4621b56afe5150366c77.jpeg#pic_center
Map接口的特点:
1.用于存储恣意键值对(Key–Value)
2.键:无序、无下标、不答应重复(唯一)
3.值:无序、无下标、答应重复
Map 父接口

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


[*]V put (K key , V value) // 将对象存入到集合中,关联键值。key重复则覆盖原值
[*]Object get (Object key) // 根据键获取对应的值
[*]Set // 返回所有key
[*]Collection values ( ) // 返回包含所有值的Collection集合
[*]Set <Map.Entry<K,V>> // 键值匹配的Set集合
代码演示:
package com.collection.map;


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("cn" , "中国");
      map.put("uk" , "英国");
      map.put("usa" , "美国");
      map.put("cn" , "zhongguo");// k 相同,覆盖掉 v
      System.out.println("元素个数:" + map.size());// 元素个数:3
      System.out.println(map.toString());// {usa=美国, uk=英国, cn=zhongguo}

      // 2. 删除
      // map.remove("usa","美国");
      // map.remove("usa");
      // System.out.println("删除:"+map.size());// 删除:2
      // System.out.println(map);// {uk=英国, cn=zhongguo}

      // 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>> entries = 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"));// true
      System.out.println(map.containsValue("意大利"));// false
    }
}
HashMap集合

在Java中,HashMap 是一个常用的数据结构,它实现了Map接口,答应我们通过键值对的形式存储和快速查找数据。HashMap的底层是基于哈希表(hash table)的实现,它的高效性和灵活性使其在各种编程场景中广受欢迎。
HashMap是Map接口的一个实现类(HashMap实现了Map的接口),它具有Map的特点。HashMap的底层是哈希表结构。
在 JDK 1.2版本中,线程不安全,运行效率快;答应用null 作为 key 或 value
下面是代码展示:
package com.collection.map;


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

/**
* HashMap集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 使用key 可以hashcode和equals作为重复
*/
public class Demo02 {
    public static void main(String[] args) {
      // 创建集合
      HashMap<Student, String> students= new HashMap<Student,String>();
      // 刚创建 hashMap之后没有添加元素table = null   size = 0 目的:节省空间
      // 1. 添加元素
      Student s1 = new Student("小李", 00001);
      Student s2 = new Student("小王", 00002);
      Student s3 = new Student("小赵", 00003);
      Student s4 = new Student("小孙", 00004);
      students.put(s1,"北京");
      students.put(s2,"天津");
      students.put(s3,"南京");
      students.put(s4,"上海");
      // students.put(s4,"杭州");// 不会新添加,会覆盖
      System.out.println("元素个数:"+students.size());// 元素个数:4
      System.out.println(students);// {Student{name='小赵', stId=3}=南京, Student{name='小王', stId=2}=天津, Student{name='小李', stId=1}=北京, Student{name='小孙', stId=4}=杭州}
      // 2. 删除
//      students.remove(s1);
//      students.remove(new Student("小孙", 00004));
//      System.out.println("删除之后:"+students.size());// 删除之后:3
//      System.out.println(students);// {Student{name='小赵', stId=3}=南京, Student{name='小王', stId=2}=天津, Student{name='小孙', stId=4}=上海}
      // 3. 遍历
      // 3.1 使用 keySet();
      System.out.println("-----------使用 keySet()---------------");
      Set<Student> keySet = students.keySet();
      for (Student s:
             keySet) {
            System.out.println(s+"----"+students.get(s));
      }
      /*
      -----------使用 keySet()---------------
      Student{name='小赵', stId=3}-----南京
      Student{name='小王', stId=2}-----天津
      Student{name='小李', stId=1}-----北京
      Student{name='小孙', stId=4}-----上海
         */
      // 3.2 使用 entrySet();
      System.out.println("-----------使用entrySet()--------------");
      Set<Map.Entry<Student, String>> entries = students.entrySet();
      for (Map.Entry<Student, String> s :
                entries) {
            System.out.println(s.getKey()+"-----"+s.getValue());
      }
      /*
      -----------使用entrySet()--------------
      Student{name='小赵', stId=3}-----南京
      Student{name='小王', stId=2}-----天津
      Student{name='小李', stId=1}-----北京
      Student{name='小孙', stId=4}-----上海
         */

      // 4. 判断
      System.out.println(students.containsKey(s1));// true
      System.out.println(students.containsKey(new Student("小赵", 00003)));// true
      System.out.println(students.containsValue("新疆"));// false
      System.out.println(students.isEmpty());// false

    }
}
学生类:
package com.collection.map;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name ;
    private int stId;

    public Student() {

    }

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

    public String getName() {
      return name;
    }

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

    public int getStId() {
      return stId;
    }

    public void setStId(int stId) {
      this.stId = stId;
    }

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

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

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

    @Override
    public int compareTo(Student o) {
      int n = this.stId - o.getStId();
      return n;
    }

}
源码分析:
源码分析:
    1. static final int DEFAULT_INTTIAL_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 ;
    JDK 1.8 当链表长度大于8时,调整成红黑树
    5. static final int UNTREEIFY_THRESHOLD = 6 ;
    JDK 1.8 当链表长度大于6时,调整成链表
    6. static final int MIN_TREEIFY_CAPACITY = 64 ;
    JDK 1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树
    7. transient Node<K,V>[] table ;
    哈希表中的数组
    8. size ;
    元素个数
总结:
1. HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
2. 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
3. jdk 1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的是提高执行效率
4. jdk 1.8 当链表长度小于6时,调整成链表
5. jdk 1.8 以前是链表头插入,1.8 以后是尾插入
Hashtable与Properties

Hashtable :
​ JDK1.0版本,线程安全,运行效率慢,不答应null作为key或是value
Properties:
​ Hashtable 的子类,要求key和value都是String。通常用于配置文件的读取
TreeMap

实现了SortedMap接口(是Map的子接口),可以对key自动排序
代码演示:
package com.collection.map;


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

/**
* TreeMap 的使用
* 存储结构: 红黑树
*/
public class Demo03 {
    public static void main(String[] args) {
      // 新建集合 (也可以使用定制)
      TreeMap<Student, String> treeMap = new TreeMap<>();
      // 1. 添加元素
      Student s1 = new Student("小李", 00001);
      Student s2 = new Student("小王", 00002);
      Student s3 = new Student("小赵", 00003);
      Student s4 = new Student("小孙", 00004);
      treeMap.put(s1,"北京");
      treeMap.put(s2,"上海");
      treeMap.put(s3,"广州");
      treeMap.put(s4,"深圳");
      // treeMap.put(s3,"香港");// 无法插入数据,但会把value值替换掉
      System.out.println("元素个数:"+treeMap.size());// 元素个数:4
      System.out.println(treeMap);// {Student{name='小李', stId=1}=北京, Student{name='小王', stId=2}=上海, Student{name='小赵', stId=3}=香港, Student{name='小孙', stId=4}=深圳}

      // 2. 删除
//      treeMap.remove(s1);
//      treeMap.remove(new Student("小孙", 00004));
//      System.out.println("删除之后:"+treeMap.size());// 删除之后:2
//      System.out.println(treeMap);// {Student{name='小王', stId=2}=上海, Student{name='小赵', stId=3}=广州}

      // 3. 遍历
      // 3.1 使用 keySet();
      System.out.println("-------使用 keySet()---------");
      for (Student key:
             treeMap.keySet()) {
            System.out.println(key+"-----"+treeMap.get(key));
      }
      /*
      -------使用 keySet()---------
      Student{name='小李', stId=1}-----北京
      Student{name='小王', stId=2}-----上海
      Student{name='小赵', stId=3}-----广州
      Student{name='小孙', stId=4}-----深圳
         */
      // 3.2 使用 entrySet();
      System.out.println("-------使用 entrySet()---------");
      for (Map.Entry<Student, String> entry :
                treeMap.entrySet()) {
            System.out.println(entry.getKey()+"----"+entry.getValue());
      }
      /*
      -------使用 entrySet()---------
      Student{name='小李', stId=1}----北京
      Student{name='小王', stId=2}----上海
      Student{name='小赵', stId=3}----广州
      Student{name='小孙', stId=4}----深圳
         */
      // 4. 判断
      System.out.println(treeMap.containsKey(s2));// true
      System.out.println(treeMap.containsKey(new Student("小王", 00002)));// true
      System.out.println(treeMap.containsValue("南京"));// false
      System.out.println(treeMap.isEmpty());// false
    }
}
Collections工具类

概念:集合工具类,界说了除了存取以外的集合常用方法
方法:


[*]public static void reverse (List<?> list) // 反转集合中元素的顺序
[*]public static void shuffer (List<?> list) // 随机重置集合元素的顺序
[*]public static void sort (List<?> list) // 升序顺序(元素范例必须实现Comparable接口)
代码演示:
package com.collection.map;

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(58);
      list.add(41);
      list.add(77);
      list.add(26);
      list.add(18);

      // sort 排序
      System.out.println("----------sort---------");
      System.out.println("排序之前:"+list);// 排序之前:
      Collections.sort(list);
      System.out.println("排序之后:"+list);// 排序之后:

      // binarySearch 二分查找
      System.out.println("--------binarySearch----------");
      int i = Collections.binarySearch(list,25);// -2
      int i1 = Collections.binarySearch(list,58);// 3
      System.out.println(i);
      System.out.println(i1);

      // copy 复制
      System.out.println("------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);//

      // reverse 反转
      System.out.println("-------reverse-------------");
      Collections.reverse(list);
      System.out.println("反转之后:"+list);// 反转之后:

      // shuffle 打乱
      System.out.println("--------shuffle--------");
      Collections.shuffle(list);
      System.out.println("打乱之后:"+list);// 打乱之后:

      // 补充:
      // list转数组
      System.out.println("--------list转数组-------");
      Integer[] arr = list.toArray(new Integer);
      Integer[] arr1 = list.toArray(new Integer);
      System.out.println(arr.length);// 5
      System.out.println(Arrays.toString(arr));//
      System.out.println(Arrays.toString(arr1));//

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

    }
}
集合总结



[*]集合的概念:

[*]对象的容器,和数组类似,界说了对多个对象进行操作的常用方法

[*]List集合

[*]有序、有下标、元素可以重复。(Arraylist、LinkedList、Vector)

[*]Set集合

[*]无序、无下标、元素不可重复。(HashSet、TreeSet)

[*]Map集合

[*]存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable、TreeMap)

[*]Collections

[*]集合工具类,界说了除了存取以外的集合常用方法。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Java集合(完整版)