java学习之路8——Java集合框架

一、什么是集合

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

二、Collection体系集合

在这里插入图片描述

1、Collection父接口

  • 特点:代表一组任意类型的对象,无序、无下标、不能重复。
  • 方法:
    • boolean add(Object obj) //添加一个对象。
    • boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中。
    • void clear() //清空此集合中的所有对象。
    • boolean contains(Object o) //检查此集合中是否包含o对象
    • boolean equals(Object o)//比较此集合是否与指定对象相等。
    • boolean isEmpty) //判断此集合是否为空
    • boolean remove(0bject o) //在此集合中移除o对象.
    • int size() //返回此集合中的元素个数。
    • Object[] toArray() //将此集合转换成数组。
package com.jjl.Collection;

/*
Collection接口的是使用
1、添加元素
2、删除记录
3、遍历元素
4、判断
 */

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("榴莲");
        collection.add("香蕉");
        System.out.println("元素个数"+collection.size());
        System.out.println(collection);
        //2、删除
        collection.remove("香蕉");
        //collection.clear();//清空
        System.out.println("删除之后的个数"+collection.size());
        //遍历元素
        //遍历方法一:增强for
        for (Object object : collection){
            System.out.println(object);
        }
        //遍历方法二:迭代器(专门用来遍历集合的一种方法)
        //迭代器iterator
        //hasNext();有没有下一个元素
        //Next();获取下一个元素
        //remove();删除当前元素
        Iterator it=collection.iterator();
        while (it.hasNext()){
            String object= (String)it.next();
            System.out.println(object);
            //it.remove();//删除
        }
        //System.out.println("迭代删除之后的个数"+collection.size());

        //判断是否有某个元素
        System.out.println(collection.contains("西瓜"));
        //判断是否为空
        System.out.println(collection.isEmpty());
    }
}
输出:
元素个数4
[苹果, 西瓜, 榴莲, 香蕉]
删除之后的个数3
苹果
西瓜
榴莲
苹果
西瓜
榴莲
true
false

实际应用

package com.jjl.Collection;

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

主程序调用

package com.jjl.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("张三",23);
        Student s2=new Student("张四",24);
        Student s3=new Student("张五",25);
        //1添加数据
        collection.add(s1);
        collection.add(s2);
        collection.add(s3);
        System.out.println("元素个数"+collection.size());
        System.out.println(collection.toString());

        //增强for循环
        System.out.println("=========增强for循环遍历=========");
        for (Object object : collection){
            Student s=(Student) object;
            System.out.println(s.toString());
        }

        //迭代器:hasNext() next(); remove(); 迭代器过程中不能使用collection的删除方法
        System.out.println("=========迭代器Iterator遍历=========");
        Iterator it = collection.iterator();
        while (it.hasNext()){
            Student s = (Student) it.next();
            System.out.println(s);
        }
    }
}
输出:
元素个数3
[Student{name='张三', age=23}, Student{name='张四', age=24}, Student{name='张五', age=25}]
=========增强for循环遍历=========
Student{name='张三', age=23}
Student{name='张四', age=24}
Student{name='张五', age=25}
=========迭代器Iterator遍历=========
Student{name='张三', age=23}
Student{name='张四', age=24}
Student{name='张五', age=25}

2、List子接口

  • 特点:有下标、有序、元素可以重复
  • 方法
    • void add (int,index,Object o) //在index位置插入对象o.
    • boolean addAll(int index,Collection c) //将一个集合中的元素添加到此集合中的index位置。
    • 0bject get(int index) //返回集合中指定位置的元素。
    • List subList(int fromIndex,int toIndex) //返回fromIndex和toIndex之间的集合元素。
package com.jjl.Collection;

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

/*
List子接口的使用
 */
public class Demo03 {
    public static void main(String[] args) {
        //先创建一个集合
        List list=new ArrayList<>();
        //添加元素
        list.add("苹果");
        list.add("vivo");
        list.add(0,"Lenovo");
        System.out.println("元素个数"+list.size());
        System.out.println(list.toString());
        //删除元素
        //list.remove(0);//删除一个元素
        //遍历
        //使用for
        System.out.println("=========使用for遍历==========");
        for (int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        //增强for
        System.out.println("===============增强for遍历=============");
        for (Object object:list){
            System.out.println(object);
        }

        //使用迭代器
        System.out.println("============使用迭代器遍历=============");
        Iterator it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        //使用列表迭代器,ListIterator可以向前向后遍历,可以添加删除元素
        System.out.println("============使用列表迭代器===========");
        ListIterator lit=list.listIterator();
        System.out.println("==========从前往后============");
        while (lit.hasNext()){
            System.out.println(lit.nextIndex()+":"+lit.next());//打印角标和属性
        }
        System.out.println("==========从后往前============");
        while (lit.hasPrevious()){
            System.out.println(lit.previousIndex()+":"+lit.previous());//打印角标和属性
        }

        //判断
        System.out.println(list.contains("苹果"));
        System.out.println(list.isEmpty());

        //获取位置(下标)
        System.out.println(list.indexOf("vivo"));

    }
}
输出:
元素个数3
[Lenovo, 苹果, vivo]
=========使用for遍历==========
Lenovo
苹果
vivo
===============增强for遍历=============
Lenovo
苹果
vivo
============使用迭代器遍历=============
Lenovo
苹果
vivo
============使用列表迭代器===========
==========从前往后============
0:Lenovo
1:苹果
2:vivo
==========从后往前============
2:vivo
1:苹果
0:Lenovo
true
false
2

List接口使用2

package com.jjl.Collection;

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

public class Demo04 {
    public static void main(String[] args) {
        //创建集合
        List list=new ArrayList();
        //添加数字数据(自动装箱)
        list.add(20);
        list.add(30);
        list.add(40);
        list.add(50);
        list.add(60);
        System.out.println("元素个数:"+list.size());
        System.out.println(list.toString());
        //删除元素(默认使用脚本删除,不能之间使用元素删除)
        //list.remove(0);
        //如果要使用元素属性删除,需要将元素转成Integer
        list.remove(new Integer(20));
        System.out.println("删除后的元素个数:"+list.size());
        System.out.println(list.toString());

        //补充方法sublist,返回子集合
        List subList=list.subList(1,3); //获取1到3的元素,包含1不包含3
        System.out.println(subList.toString());

    }
}
输出:
元素个数:5
[20, 30, 40, 50, 60]
删除后的元素个数:4
[30, 40, 50, 60]
[40, 50]

3、List实现类

  • ArrayList
    • 数组结构实现,查询块、增删慢;
    • JDK1.2版本,运行效率块、线程不安全。
    • 源码分析:
      • 默认容量:DEFAULT_CAPACITY = 10;
        • 如果没有向集合中添加任何元素时,容量就是:0
      • 存放元素的数组:transient Object[] elementData
      • 实际元素个数:size
  • Vector:
    • 数组结构实现,查询快、增删慢;
    • ·JDK1.0版本,运行效率慢、线程安全。
  • LinkedList:
    • 链表结构实现,增删快,查询慢。

3.1、ArrayList

package com.jjl.Collection;

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

/*
ArrayList的使用
存储结构:数组,查找遍历速度快,增删慢
 */
public class Demo5 {
    public static void main(String[] args) {
        //创建集合
        ArrayList arrayList=new ArrayList<>();
        //1添加元素
        Student s1=new Student("可可",18);
        Student s2=new Student("爱爱",17);
        Student s4=new Student("明明",25);
        Student s3=new Student("小小",19);
        Student s5=new Student("玲玲",20);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s4);
        arrayList.add(s5);
        System.out.println("============元素总个数===========");
        System.out.println("元素个数"+arrayList.size());
        System.out.println("\n========打印所有元素===========");
        System.out.println(arrayList.toString());
        //删除
        //方法一:
        System.out.println("\n=======使用下标或者元素属性名称删除元素===========");
        arrayList.remove(1);//可以用下标,也可以用元素属性
        System.out.println(arrayList.toString());
        //方法二:
        System.out.println("\n========使用元素源数据进行删除,需要重写object方法===========");
        arrayList.remove(new Student("小小",19));//如果需要这种方法删除,则就要重写Student的obj方法
        System.out.println(arrayList.toString());

        //遍历(使用迭代器)
        System.out.println("\n============迭代器遍历法===========");
        Iterator it=arrayList.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.toString());
        }
        //遍历(列表迭代器)
        System.out.println("\n============列表迭代器遍历法===========");
        ListIterator lit= arrayList.listIterator();
        while (lit.hasNext()) {
            Student s = (Student) lit.next();
            System.out.println(s.toString());
        }
        //判断
        System.out.println("\n============判断元素是否存在===========");
        System.out.println(arrayList.contains(new Student("玲玲",20)));//此方法只能在重写了equals方法之后才能使用
        System.out.println(arrayList.isEmpty());//判断是否为空

        //查找
        System.out.println("\n============查找元素的下标===========");
        System.out.println(arrayList.indexOf(s1));
    }
}
输出:
============元素总个数===========
元素个数5

========打印所有元素===========
[Student{name='可可', age=18}, Student{name='爱爱', age=17}, Student{name='小小', age=19}, Student{name='明明', age=25}, Student{name='玲玲', age=20}]

=======使用下标或者元素属性名称删除元素===========
[Student{name='可可', age=18}, Student{name='小小', age=19}, Student{name='明明', age=25}, Student{name='玲玲', age=20}]

========使用元素源数据进行删除,需要重写equals方法===========
[Student{name='可可', age=18}, Student{name='明明', age=25}, Student{name='玲玲', age=20}]

============迭代器遍历法===========
Student{name='可可', age=18}
Student{name='明明', age=25}
Student{name='玲玲', age=20}

============列表迭代器遍历法===========
Student{name='可可', age=18}
Student{name='明明', age=25}
Student{name='玲玲', age=20}

============判断元素是否存在===========
true
false

============查找元素的下标===========
0

重写Student类的equals方法的比较方式

@Override
    public boolean equals(Object obj) {
        //判断是否为同一个对象
        if(this==obj){
            return true;
        }
        //是否为空
        if(obj==null){
            return false;
        }
        //判断是否为Student类型
        if (obj instanceof Student){
            Student s=(Student) obj;
            //比较属性
            if (this.name.equals(s.getName())&&this.age==s.getAge()){
                return true;
            }
        }

        return false;
    }

3.2、Vector

package com.jjl.Collection;

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

/*
Vector集合的使用
 */
public class Demo06 {
    public static void main(String[] args) {
        Vector vector=new Vector<>();
        vector.add("草莓");
        vector.add("芒果");
        vector.add("西瓜");
        vector.add("香蕉");
        System.out.println("元素个数"+vector.size());

        //遍历
        vector.remove(0);//可以根据角标和元素

        //遍历,可以用for
        //枚举器遍历
        Enumeration en=vector.elements();
        while (en.hasMoreElements()){
            String o=(String) en.nextElement();
            System.out.println(o);
        }

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

}
输出:
元素个数4
芒果
西瓜
香蕉
true

3.3、LinkedList

package com.jjl.Collection;

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

/*
LinkedList的使用
 */
public class Demo07 {
    public static void main(String[] args) {
        //创建集合
        LinkedList linkedList=new LinkedList<>();
        //添加元素
        Student s1=new Student("张三",23);
        Student s2=new Student("张四",24);
        Student s3=new Student("张五",25);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        linkedList.add(s3);
        System.out.println("=====打印元素个数=======");
        System.out.println("元素个数:"+linkedList.size());
        System.out.println("\n======打印所有元素=======");
        System.out.println(linkedList.toString());
        //2、删除
        linkedList.remove(new Student("张三",23));//由于重写过equals方法,所以可以使用元素内容删除
        System.out.println("\n=========删除元素之后的元素个数:===========");
        System.out.println(linkedList.size());
        //3遍历
        System.out.println("\n=====for遍历========");
        for (int i=0;i<linkedList.size();i++){
            System.out.println(linkedList.get(i));
        }
        System.out.println("\n=========增强for遍历========");
        for(Object object:linkedList){
            Student s=(Student) object;
            System.out.println(s.toString());
        }
        System.out.println("\n======迭代器遍历========");
        Iterator it=linkedList.iterator();
        while (it.hasNext()){
            Student s=(Student) it.next();
            System.out.println(s.toString());
        }
        System.out.println("\n======列表迭代器遍历========");
        ListIterator lit=linkedList.listIterator();
        while (lit.hasNext()){
            Student s=(Student) lit.next();
            System.out.println(s.toString());
        }
        System.out.println("\n======判断========");
        System.out.println(linkedList.contains(s2));//判断元素是否存在
        System.out.println(linkedList.isEmpty());//判断是否为空
        System.out.println("\n======查找========");
        System.out.println(linkedList.indexOf(s3));


    }
}
输出:
=====打印元素个数=======
元素个数:4

======打印所有元素=======
[Student{name='张三', age=23}, Student{name='张四', age=24}, Student{name='张五', age=25}, Student{name='张五', age=25}]

=========删除元素之后的元素个数:===========
3

=====for遍历========
Student{name='张四', age=24}
Student{name='张五', age=25}
Student{name='张五', age=25}

=========增强for遍历========
Student{name='张四', age=24}
Student{name='张五', age=25}
Student{name='张五', age=25}

======迭代器遍历========
Student{name='张四', age=24}
Student{name='张五', age=25}
Student{name='张五', age=25}

======列表迭代器遍历========
Student{name='张四', age=24}
Student{name='张五', age=25}
Student{name='张五', age=25}

======判断========
true
false

======查找========
1

三、泛型

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

1、泛型类

创建泛型类

package com.jjl.MyGeneric;

/*
泛型类
语法,类名
T是类型占位符,表示一种引用类型,如果编写多个使用,逗号隔开。
 */
public class Demo01<T> {
    //使用泛型
    //1创建变量
    T t;
    //作为方法的参数
    public void show(T t){
        System.out.println(t);

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

主程序测试

package com.jjl.MyGeneric;

import com.jjl.Exception.Demo02.MyException;

public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类T对象
        //注意:1泛型只能使用引用类型。
        //2不同泛型之间不能相互复制
        Demo01<String> demo01=new Demo01<String>();
        //demo01.t="hello";
        demo01.show("大家好");
        String string=demo01.getT();

        Demo01<Integer> demo011=new Demo01<Integer>();
        //demo011.t=100;
        demo011.show(200);
        Integer integer= demo011.getT();
    }
}
输出:
大家好
200

2、泛型接口

创建接口

package com.jjl.MyGeneric;

/*
泛型接口
语法,接口<T>
注意,不能使用泛型创建静态常量
 */
public interface MyInterface<T> {
    //String name="张三";
    T server(T t);

}

接口实现类:方法一
直接指定参数类型

package com.jjl.MyGeneric;

public class MyInterfaceMpl implements MyInterface<String>{
    @Override
    public String server(String s) {
        System.out.println(s);
        return s;
    }
}

接口实现类:方法二
不指定参数类型,让调用实现类时指定

package com.jjl.MyGeneric;

public class MyInterfacemp2<T> implements MyInterface<T>{
    @Override
    public T server(T t) {
        System.out.println(t);
        return t;
    }
}

主程序调用

		//方法一
        MyInterfaceMpl impl=new MyInterfaceMpl();
        impl.server("xxxxxxxxxxxx");
		
		//方法二
        MyInterfacemp2<Integer> ipl2=new MyInterfacemp2<>();
        ipl2.server(2000);

3、泛型方法

创建一个泛型方法

package com.jjl.MyGeneric;

/*
泛型方法
语法:<T>方法返回值
 */
public class MyGenericthod {
    //泛型方法
    //格式一:
    public <T> void show(T t){
        System.out.println("泛型方法"+t);
    }

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

主程序调用

//调用泛型方法
        MyGenericthod myGenericthod=new MyGenericthod();
        //不用指定类型,会自动根据给的值确定类型
        myGenericthod.show("字符串");
        myGenericthod.show(200);
        myGenericthod.show(1.14);
输出:
泛型方法字符串
泛型方法200
泛型方法1.14

4、泛型集合

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

import com.jjl.Collection.Student;

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

public class Demo02 {
    public static void main(String[] args) {
        //通过泛型,指定集合里的数据类型
        ArrayList<String> arrayList=new ArrayList<String>();
        arrayList.add("xxxx");
        arrayList.add("yyy");

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

        ArrayList<Student> arrayList2=new ArrayList<Student>();
        Student s1=new Student("张三",23);
        Student s2=new Student("张四",24);
        Student s3=new Student("张五",25);
        arrayList2.add(s1);
        arrayList2.add(s2);
        arrayList2.add(s3);

        Iterator<Student> it= arrayList2.iterator();
        while (it.hasNext()){
            Student s=it.next();//由于“Iterator<Student>”已经指定了迭代器的类型,所以不用再转成student类型了。
            System.out.println(s.toString());
        }

    }
}
输出:
xxxx
yyy
Student{name='张三', age=23}
Student{name='张四', age=24}
Student{name='张五', age=25}

四、Set集合

  • 特点:无须、无下标、元素不可重复。
  • 方法:全部继承自Collection中的方法。
package com.jjl.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("xiaomi");
        set.add("vivo");
        set.add("oppo");
        set.add("HUAWEI");
        System.out.println("元素个数:"+set.size());
        System.out.println(set.toString());

        //2删除
        set.remove("xiaomi");

        //3遍历
        //方法一:增强for
        System.out.println("\n=========增强for遍历=========");
        for (String string:set){
            System.out.println(string);
        }
        //方法二:迭代器
        System.out.println("\n=========使用迭代器遍历=========");
        Iterator<String> it=set.iterator();
        while (it.hasNext()){
            String sting= it.next();
            System.out.println(sting);
        }

        //判断
        System.out.println("\n=========判断元素是否存在=========");
        System.out.println(set.contains("HUAWEI"));
        System.out.println("\n=========判断是否为空=========");
        System.out.println(set.isEmpty());


    }
}
输出:
元素个数:4
[xiaomi, oppo, vivo, HUAWEI]

=========增强for遍历=========
oppo
vivo
HUAWEI

=========使用迭代器遍历=========
oppo
vivo
HUAWEI

=========判断元素是否存在=========
true

=========判断是否为空=========
false

1、Set实现类

1.1HashSet 【重点】

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

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

/*
HashSet集合的使用
存储结构:哈希表(数组+链表+红黑树)
 */
public class Demo02 {
    public static void main(String[] args) {
        //新建集合
        HashSet<String> hashSet=new HashSet<String>();
        //1添加元素
        hashSet.add("刘德华");
        hashSet.add("成龙");
        hashSet.add("杨幂");
        hashSet.add("热巴");
        System.out.println("元素个数:"+hashSet.size());
        System.out.println(hashSet.toString());

        //删除
        System.out.println("\n=======删除后的元素个数========");
        hashSet.remove("热巴");
        System.out.println("元素个数:"+hashSet.size());

        //遍历增强for
        System.out.println("\n=======增强for遍历========");
        for (String string:hashSet){
            System.out.println(string);
        }
        System.out.println("\n=======迭代器遍历========");
        Iterator<String> it=hashSet.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        //判断
        System.out.println("\n=======判断元素是否存在,判断元素是否为空========");
        System.out.println(hashSet.contains("热巴"));
        System.out.println(hashSet.isEmpty());
    }

}
输出:
元素个数:4
[成龙, 杨幂, 热巴, 刘德华]

=======删除后的元素个数========
元素个数:3

=======增强for遍历========
成龙
杨幂
刘德华

=======迭代器遍历========
成龙
杨幂
刘德华

=======判断元素是否存在,判断元素是否为空========
false
false

重写hashcode和equlas用于排重的方法
新建set类

package com.jjl.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 +
                '}';
    }

    //以下是通过快捷方式一键生成的hashcode和equals用于去重的方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
    


    //手动写的hashcode和equals用于去重的方法
    //    @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和equlas用于排重的方法的快捷方法:
在这里插入图片描述
在这里插入图片描述

主程序调用

package com.jjl.Set;

import java.util.HashSet;

/*
hashset使用
存储过程:
(1)根据hashcode计算保存的位置。如果此位置为空。则直接保存。如果不为空执行第二步。
(2)再执行equals方法。如果equals方法为true,则认为是重复,否则形成链表

 */
public class Demo03 {
    public static void main(String[] args) {
        HashSet<Person> person=new HashSet<>();
        Person p1=new Person("刘德华",50);
        Person p2=new Person("成龙",60);
        Person p3=new Person("林志玲",20);
        Person p4=new Person("宋小宝",10);
        person.add(p1);
        person.add(p2);
        person.add(p3);
        person.add(p4);
        person.add(p4);//以这种方式,Java会认为是重复数据,不能加入Hashset
        //以这种方式又可以加入重复的的数据,如果想让它加入不进去,就需要重写Person类的hashcode方法和equals方法
        person.add(new Person("宋小宝",10));

        System.out.println("打印元素个数:"+person.size());
        System.out.println(person);
    }
}

1.2、TreeSet:

  • 基于排列顺序实现元素不重复。
  • 实现了SortedSet接口,对集合元素自动排序。
  • 元素对象的类型必须实现Comparable接口,指定排序规则。
  • 通过CompareTo方法确定是否为重复元素。

简单使用

package com.jjl.Set;

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

/*
TreeSet的使用
存储结构:红黑树
 */
public class Demo04 {
    public static void main(String[] args) {
        //1创建集合
        TreeSet<String> treeSet=new TreeSet<>();
        //1添加元素
        treeSet.add("xyz");
        treeSet.add("abc");
        treeSet.add("hello");
        System.out.println("打印元素个数:"+treeSet.size());
        System.out.println(treeSet);//自动排序

        treeSet.remove("hello");
        System.out.println("\n删除后元素个数:"+treeSet.size());

        System.out.println("\n=====增强for遍历=========");
        for(String string:treeSet){
            System.out.println(string);
        }
        System.out.println("\n=====迭代器遍历=========");
        Iterator<String> it=treeSet.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        System.out.println("\n=====判断=========");
        System.out.println(treeSet.contains("abc"));

    }
}
打印:
打印元素个数:3
[abc, hello, xyz]

删除后元素个数:2

=====增强for遍历=========
abc
xyz

=====迭代器遍历=========
abc
xyz

=====判断=========
true

复杂参数

package com.jjl.Set;

import java.util.TreeSet;
/*
存储方式:红黑树
要求:元素必须要实现Comparable接口,compareTo()方法的返回值为0时,则意味着为重复的
 */
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<Person> person=new TreeSet<>();
        Person p1=new Person("刘德华",50);
        Person p2=new Person("成龙",60);
        Person p3=new Person("林志玲",20);
        Person p4=new Person("宋小宝",10);
        person.add(p1);
        person.add(p2);
        person.add(p3);
        person.add(p4);
        System.out.println("打印元素个数:"+ person.size());
        System.out.println(person);

    }
}

由于上面treeset的元素时Person类,所以就需要Person实现Comparable接口,compareTo()方法的返回值为0时,则意味着为重复的

package com.jjl.Set;

import java.util.Objects;

public class Person implements Comparable<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 +
                '}';
    }

    //以下是通过快捷方式一键生成的hashcode和equals用于去重的方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    /**
     * @param o the object to be compared.
     * @return
     */
    //先按姓名比,再按年龄比
    @Override
    public int compareTo(Person o) {
        int n1=this.getName().compareTo(o.getName());
        int n2=this.age-o.getAge();

        return n1==0?n2:n1;
    }

    //手动写的hashcode和equals用于去重的方法
    //    @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;
//    }

}

定制比较,不用单独在Person类实现Comparable接口

package com.jjl.Set;

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

/*
TreeSet集合的使用
Comparator:实现定制比较

 */
public class Demo06 {
    public static void main(String[] args) {
        //通过匿名内部类的方式,实现比较方式,就不用在Person类里面去实现实现Comparable接口了
        TreeSet<Person> person=new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int n1=o1.getAge()-o2.getAge();
                int n2=o1.getName().compareTo(o2.getName());
                return n1==0?n2:n1;
            }
        });
        Person p1=new Person("刘德华",50);
        Person p2=new Person("成龙",60);
        Person p3=new Person("林志玲",20);
        Person p4=new Person("宋小宝",10);
        person.add(p1);
        person.add(p2);
        person.add(p3);
        person.add(p4);
        System.out.println("打印元素个数:"+ person.size());
        System.out.println(person);


    }
}

案例
使用Treeset集合实现字符串按照长度进行排序

package com.jjl.Set;

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

/*
通过定制比较规则
使用Treeset集合实现字符串按照长度进行排序
 */
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("helloword");
        treeSet.add("pingguo");
        treeSet.add("lisi");
        treeSet.add("zhangsan");
        treeSet.add("beijing");
        treeSet.add("cat");
        treeSet.add("nanjing");
        treeSet.add("xian");
        System.out.println(treeSet.toString());
    }
}
输出:
[cat, lisi, xian, beijing, nanjing, pingguo, zhangsan, helloword]

三、Map集合

在这里插入图片描述

1、Map父接口

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

基本使用

package com.jjl.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<>();
        map.put("CN","中国");
        map.put("UK","英国");
        map.put("USA","美国");
        map.put("JP","日本");
        //map.put("JP","riben");//如果,添加重复的value,那么则会覆盖前面的value和key。
        System.out.println("打印元素个数:"+map.size());
        System.out.println(map);

        System.out.println("\n=========删除之后的个数=========");
        map.remove("JP");
        System.out.println("打印元素个数:"+map.size());
        //3遍历
        //使用keySet();
        System.out.println("\n========keyset()遍历===========");
        Set<String> keyset=map.keySet();
        for (String key:keyset){
            System.out.println(key+":"+map.get(key));
        }
        //使用entryset()方法
        System.out.println("\n========entrySet遍历===========");
        //Set<Map.Entry<String,String>> entries=map.entrySet();
        for(Map.Entry<String,String>entry: map.entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }

        System.out.println("\n=====判断=====");
        System.out.println(map.containsKey("CN"));
        System.out.println(map.containsValue("俄罗斯"));
输出:
打印元素个数:4
{USA=美国, UK=英国, JP=日本, CN=中国}

=========删除之后的个数=========
打印元素个数:3

========keyset()遍历===========
USA:美国
UK:英国
CN:中国

========entrySet遍历===========
USA:美国
UK:英国
CN:中国

=====判断=====
true
false     
    }
}

2、Map集合的实现类

2.1、HashMap【重点】:

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

新增一个学生类
为了确保key的不可重复性,所以需要重写Hashcode和equls方法

package com.jjl.Map;

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

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getStuNo() {
        return stuNo;
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;

        Student student = (Student) o;

        if (stuNo != student.stuNo) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + stuNo;
        return result;
    }
}

主程序测试

package com.jjl.Map;

import com.jjl.Set.Person;

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

/*
HashMap集合使用
存储结构:哈希表(数组+链表+红黑树)
使用KEY的Hashcode和equals作为重复依据
 */
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        HashMap<Student,String> student=new HashMap<Student,String>();
        //添加元素
        Student s1=new Student("张一",100);
        Student s2=new Student("张二",200);
        Student s3=new Student("张三",300);
        student.put(s1,"北京");
        student.put(s2,"成都");
        student.put(s3,"重庆");
        //通过new的方法可以实现元素重复添加,如果想要new也加不进去,就需要重写Hashcode和equals
        student.put(new Student("张三",300),"杭州");
        System.out.println("打印元素个数:"+student.size());
        System.out.println(student);

        System.out.println("\n==========删除之后的元素个数=======");
        student.remove(s1);
        System.out.println(student.size());

        System.out.println("\n========keySet遍历===========");
        for(Student key:student.keySet()){
            System.out.println(key+":"+student.get(key));
        }
        System.out.println("\n========Entry遍历===========");
        for(Map.Entry<Student,String> entry:student.entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }

        //判断
        System.out.println("\n========判断key或者value是否存在===========");
        System.out.println(student.containsKey(s2));
        System.out.println(student.containsValue("成都"));


    }
}
输出:
打印元素个数:3
{Student{name='张二', stuNo=200}=成都, Student{name='张一', stuNo=100}=北京, Student{name='张三', stuNo=300}=杭州}

==========删除之后的元素个数=======
2

========keySet遍历===========
Student{name='张二', stuNo=200}:成都
Student{name='张三', stuNo=300}:杭州

========Entry遍历===========
Student{name='张二', stuNo=200}:成都
Student{name='张三', stuNo=300}:杭州

========判断key或者value是否存在===========
true
true

总结:

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

3、Hashtable:

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

4、TreeMap :

  • 实现了SortedMap接口(是Map的子接口),可以对key自动排序。
  • 要求元素实现Comparable接口,重写比较器

让元素类实现Comparable接口
在这里插入图片描述
在这里插入图片描述
主程序测试

package com.jjl.Map;
/*
TreeMap的使用
 */

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

public class Demo03 {
    public static void main(String[] args) {
        //新建集合
        TreeMap<Student, String> treemap=new TreeMap<>();
        Student s1=new Student("张一",100);
        Student s2=new Student("张二",200);
        Student s3=new Student("张三",300);
        treemap.put(s1,"北京");
        treemap.put(s2,"成都");
        treemap.put(s3,"重庆");
        System.out.println("打印元素个数:"+treemap.size());
        System.out.println(treemap);

        //遍历
        System.out.println("\n======entryset()遍历====");
        for (Student key : treemap.keySet()){
            System.out.println(key+":"+treemap.get(key));
        }
        System.out.println("\n======entryset()遍历====");
        for (Map.Entry<Student,String> entry:treemap.entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
    }
}
输出:
打印元素个数:3
{Student{name='张一', stuNo=100}=北京, Student{name='张二', stuNo=200}=成都, Student{name='张三', stuNo=300}=重庆}

======entryset()遍历====
Student{name='张一', stuNo=100}:北京
Student{name='张二', stuNo=200}:成都
Student{name='张三', stuNo=300}:重庆

======entryset()遍历====
Student{name='张一', stuNo=100}:北京
Student{name='张二', stuNo=200}:成都
Student{name='张三', stuNo=300}:重庆

当元素类不能实现Comparable接口时,可以使用定制比较

package com.jjl.Map;

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

public class Demo04 {
    public static void main(String[] args) {
        //新建集合(定制比较)
        TreeMap<Student, String> treemap=new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n2= o1.getStuNo()-o2.getStuNo();
                return n2;
            }
        });
        Student s1=new Student("张一",100);
        Student s2=new Student("张二",200);
        Student s3=new Student("张三",300);
        treemap.put(s1,"北京");
        treemap.put(s2,"成都");
        treemap.put(s3,"重庆");
        System.out.println("打印元素个数:"+treemap.size());
        System.out.println(treemap);

        //遍历
        System.out.println("\n======entryset()遍历====");
        for (Student key : treemap.keySet()){
            System.out.println(key+":"+treemap.get(key));
        }
        System.out.println("\n======entryset()遍历====");
        for (Map.Entry<Student,String> entry:treemap.entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
    }
}

5、Colletions工具类

  • 概念:集合工具类,定义了除了存取以外的集合常用方法。
  • 方法:
    • public static void reverse(List<?> list) //反转集合中元素的顺序
    • public static void shuffle(List<?> list) //随机重置集合元素的顺序
    • public static void sort(List< T > list) //升序排序(元素类型必须实现Comparable接口)
package com.jjl.Map;

import java.lang.reflect.Array;
import java.util.*;

/*
Colletions工具类的使用
 */
public class Demo05 {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList<>();
        list.add(20);
        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());

        System.out.println("\n======binarySearch,二分查找======");
        //binarySearch,二分查找,如果找到了,则返回该元素的下标,如果没找到,则就返回一个负数
        int i=Collections.binarySearch(list,6);
        System.out.println(i);

        //copy复制
        //新建一个目标集合
        System.out.println("\n===========copy复制=====");
        List<Integer> dest=new ArrayList<>();
        //如果直接用“Collections.copy(dest,list);”复制元素,会报错,因为dest里面没有元素,默认大小为0,而list里面已经有5个元素了。
        //为了保证目标集合长度和源集合长的时一样的,则需要用for往目标集合里面添加一些占位元素。
        for (int k=0;k<list.size();k++){
            dest.add(0);
        }
        Collections.copy(dest,list);
        System.out.println(dest);

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

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

        //补充,list转成数组
        System.out.println("\n=========list转成数组============");
        Integer[] arr=list.toArray(new Integer[0]);
        System.out.println(arr.length);
        System.out.println(Arrays.toString(arr));

        System.out.println("\n=========数组(每个元素都是字符串)转成集合============");
        String[] name={"张一","张二","张三"};
        //通过这种方式转成的集合,它是一个受限集合,不能添加和删除元素
        List<String> list2=Arrays.asList(name);
        System.out.println(list2);

        System.out.println("\n=========数组(每个元素都是数字)转成集合============");
        //将基本类型数组转换为集合,需要修改为包装类
        Integer[] nums={100,200,300,400,500};
        List<Integer> list3=Arrays.asList(nums);
        System.out.println(list3);
    }
}
输出:
排序前:[20, 5, 12, 30, 6]
排序之后:[5, 6, 12, 20, 30]

======binarySearch,二分查找======
1

===========copy复制=====
[5, 6, 12, 20, 30]

反转之后:[30, 20, 12, 6, 5]

打乱之后:[12, 5, 20, 30, 6]

=========list转成数组============
5
[12, 5, 20, 30, 6]

=========数组(每个元素都是字符串)转成集合============
[张一, 张二, 张三]

=========数组(每个元素都是数字)转成集合============
[100, 200, 300, 400, 500]

四、集合总结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XL's妃妃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值