Java集合

集合

简介

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

与数组的区别

  1. 元素类型

集合:只能是引用类型(存储基本类型时自动装箱)

数组:基本类型,引用类型

  1. 元素个数

集合:个数不固定,可以任意扩容

数组:固定,不能改变容量

Java的集合体系

单列集合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7tSqbY7i-1630411322597)(D:\markdown图片\捕获1.PNG)]

双列集合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ulNwsxv-1630411322606)(D:\markdown图片\捕获2.PNG)]

Collection接口

实例一

package com.collection.one;

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

public class CollectionTestFirst {
    public static void main(String[] args) {
        //collection接口的基本使用一
        //创建对象
        Collection collection = new ArrayList();//ArrayList是有序的
        //1.添加元素
        collection.add("苹果");
        collection.add("橘子");
        collection.add("山竹");
        System.out.println("集合的元素个数:"+collection.size());
        System.out.println(collection);
        //2.遍历元素
        //2.1通过增强for循环来遍历
        System.out.println("-----通过增强for循环来遍历-----");
        for (Object o : collection) {
            System.out.println(o);
        }
        //2.2通过迭代器来遍历
        System.out.println("-----通过迭代器来遍历-----");
        Iterator it = collection.iterator();
        while (it.hasNext()) {
            //Object o = it.next();
            String s = (String)it.next(); //当前集合中存储的是字符串类型,所以可以强制类型转换成字符串类型
            System.out.println(s);
            //这里不能使用collection中的remove()方法进行删除元素,只能用迭代器提供的remove()方法进行删除
            //it.remove();
        }
        //System.out.println("元素个数:"+collection.size());

        //3.判断
        //判断集合中是否包含“榴莲”
        System.out.println(collection.contains("榴莲"));
        //判断集合中是否包含“山竹”
        System.out.println(collection.contains("山竹"));
        //判断集合是否是空
        System.out.println(collection.isEmpty());

        //4.删除元素
        //删除指定元素
        collection.remove("苹果");
        System.out.println(collection);
        //清空集合
        collection.clear();
        System.out.println("元素个数:"+collection.size());
    }
}

实例二

//首先建立一个Student类

package com.collection.one;

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


//测试类
package com.collection.one;

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

public class CollectionTestSecond {
    public static void main(String[] args) {
        Student s1 = new Student("张三",18);
        Student s2 = new Student("李四",20);
        Student s3 = new Student("王二",19);
        //创建集合
        Collection collection = new ArrayList();
        //1.添加元素
        collection.add(s1);
        collection.add(s2);
        collection.add(s3);
        System.out.println("元素个数:"+collection.size());
        System.out.println(collection.toString());//不加toString()也可以
        //2.遍历元素
        //2.1通过增强for遍历元素
        System.out.println("-----增强for进行遍历-----");
        for (Object o : collection) {
            Student s = (Student) o;
            System.out.println(s);
        }
        //2.2通过迭代器进行遍历
        System.out.println("-----迭代器进行遍历-----");
        Iterator it = collection.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s);
            //此处不能调用collection的任何方法,例如collection的remove()方法,否则会产生并发修改异常
        }

        //3.判断
        //判断是否包含s1
        System.out.println(collection.contains(s1));
        //判断是否包含下列对象
        System.out.println(collection.contains(new Student("王柳",20)));
        //判断是否为空
        System.out.println(collection.isEmpty());

        //4.删除元素
        collection.remove(s1);
        System.out.println("元素个数:"+collection.size());
        //清空集合
        collection.clear();
        System.out.println("元素个数:"+collection.size());
    }
}

List接口

特点

有序,有下标,元素可以重复

常用方法

  • void add(int index,Object o) 在指定位置添加元素
  • boolean addAll(int index,Collection c) 将一个集合中的元素添加到此集合中的index位置
  • Object get(int index) 返回指定位置的元素
  • List subList(int fromIndex,int toIndex) 返回formIndex和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 list = new ArrayList();

        //1.添加元素
        list.add("华为");
        list.add("小米");
        list.add("oppo");
        System.out.println("元素个数:"+list.size());
        System.out.println(list);
        //可以在指定位置处添加元素
        list.add(3,"魅族");
        System.out.println(list);

        //2.遍历元素
        //2.1使用for循环,由于List是有下标的,因此可以使用for循环
        System.out.println("-----使用for循环-----");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        //2.2使用增强for
        System.out.println("-----使用增强for-----");
        for (Object o : list) {
            System.out.println(o);
        }

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

        //2.4使用列表迭代器
        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());
        }

        //3.判断
        System.out.println(list.contains("huawei"));
        System.out.println(list.contains("华为"));
        System.out.println(list.isEmpty());

        //4.获取
        System.out.println("-----获取0号元素-----");
        System.out.println("0号元素:"+list.get(0));

        //删除
        list.remove("华为");
        //删除指定下标的元素
        list.remove(1);
        System.out.println(list);
        list.clear();
        System.out.println(list);//空
    }
}

实例二

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();

        //添加元素
        list.add(10);
        list.add(20);
        list.add(30);
        System.out.println(list);

        //删除元素:注意!!!
        list.remove(new Integer(20));//或者把20强转成Object类
        System.out.println(list);

        //补充方法subList(),返回值仍是一个集合
        list.add(40);
        list.add(34);
        System.out.println(list);
        List list1 = list.subList(1,3);
        System.out.println(list1);//该方法的前后两个索引也是含头不含尾
    }
}

增强for

格式
for(数据类型 变量名:数组或集合对象) {
    //循环体,变量即元素
}//通常用于不需要下标的循环遍历

迭代器

遍历Collection集合的通用方式

迭代器的常用方法
  • next() 返回迭代的下一个元素对象
  • hasNext() 如果仍有元素可迭代,则返回true
  • remove() 删除当前元素
使用步骤
  1. 根据集合对象获取其对象的迭代器对象;
  2. 判断迭代器中是否有元素;
  3. 如果有就获取元素。
//举例
Iterator it = list.iterator();
while(it.hasNext()){
    String s = (String)it.next();
    System.out.println(s);
}

列表迭代器

List集合特有的迭代器,是Iterator的子接口

在迭代时,不可以通过集合对象的方法操作集合中的元素,否则会发生ConcurrentModificationException(并发修改异常)。所以,在使用迭代器时,只能用迭代器的方法操作元素,但其方法是有限的。如果想要其他操作如增加、修改时就要使用列表迭代器。

//2.4使用列表迭代器
        System.out.println("使用列表迭代器从前往后遍历");
        ListIterator lit = arrayList.listIterator();
        while (lit.hasNext()){
            String s = (String) lit.next();
            System.out.println(s);
        }
        System.out.println("使用列表迭代器从后往前遍历");
        while (lit.hasPrevious()){
            String s = (String) lit.previous();
            System.out.println(s);
        }

List接口的实现类

ArrayList类

  1. 数组结构实现,查询快,增删慢;
  2. 运行效率快,线程不安全。

Vector类

  1. 数组结构实现,查询快,增删慢;
  2. 运行效率慢,线程安全。

LinkedList类

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

ArrayList

常用方法

  • add() 添加元素
  • size() 长度
  • remove() 删除元素
  • clear() 清空
  • contains() 是否包含
  • isEmpty() 是否为空
  • indexOf() 返回下标

如果没有添加元素时,容量为0,添加一个元素后,容量为10,每次扩容大小为原来的1.5倍。(是容量,不能说长度)

实例

package com.collection.list;

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

public class Demo03 {
    //ArrayList的使用
    //数组结构实现
    public static void main(String[] args) {
        //创建集合
        ArrayList arrayList = new ArrayList();
        //1.添加元素
        arrayList.add("张杰");
        arrayList.add("尊龙");
        arrayList.add("古天乐");
        System.out.println("元素个数:"+arrayList.size());
        System.out.println(arrayList.toString());

        //2.遍历元素
        //2.1for循环
        //2.2增强for
        //2.3迭代器
        System.out.println("-----使用迭代器-----");
        Iterator it = arrayList.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println(s);
        }
        //2.4使用列表迭代器
        System.out.println("使用列表迭代器从前往后遍历");
        ListIterator lit = arrayList.listIterator();
        while (lit.hasNext()){
            String s = (String) lit.next();
            System.out.println(s);
        }
        System.out.println("使用列表迭代器从后往前遍历");
        while (lit.hasPrevious()){
            String s = (String) lit.previous();
            System.out.println(s);
        }

        //3.判断
        System.out.println(arrayList.contains("谢娜"));
        System.out.println(arrayList.isEmpty());

        //查找
        System.out.println(arrayList.indexOf("张杰"));
        System.out.println(arrayList.get(1));

        //5.删除
        arrayList.remove(2);
        System.out.println("元素个数"+arrayList.size());
    }
}

Vector

常用方法

  • add() 添加元素
  • size() 长度
  • remove() 删除元素
  • clear() 清空
  • contains() 是否包含
  • isEmpty() 是否为空
  • indexOf() 返回下标

实例

package com.collection.list;

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

public class Demo04 {
    //Vector的使用
    //数组结构实现
    public static void main(String[] args) {
        //创建集合
        Vector vector = new Vector();
        //添加元素
        vector.add("hello");
        vector.add("world");
        vector.add("man");
        //使用枚举器遍历
        Enumeration elements = vector.elements();
        while (elements.hasMoreElements()) {
            String s = (String) elements.nextElement();
            System.out.println(s);
        }
    }
}

LinkedList

常用方法

  • add() 添加元素
  • size() 长度
  • remove() 删除元素
  • clear() 清空
  • contains() 是否包含
  • isEmpty() 是否为空
  • indexOf() 返回下标

实例

package com.collection.list;

import java.util.LinkedList;

public class Demo05 {
    //LinkedList类
    //双向链表结构实现
    public static void main(String[] args) {
        //创建集合
        LinkedList linkedList = new LinkedList();
        //添加元素
        linkedList.add("you");
        linkedList.add("your");
        linkedList.add("yours");
        System.out.println("元素个数:"+linkedList.size());
        //遍历
        //判断
        //查询
        //删除

        //List的实现类方法有异曲同工之处
    }
}

泛型

简介

泛指任意类型,对具体类型的使用起到辅助作用,类似于方法的参数,其本质是参数化类型,把类型作为参数传递,常见形式有泛型类、泛型接口、泛型方法。

好处

  1. 类型安全,避免了类型转换(防止类型转换异常);
  2. 提高代码的重用性。

泛型类

package com.collection.list.demo;

/**
 * 泛型类的使用
 * 语法:类名后面+<T>
 * T是占位符,表示各种引用类型
 */
public class MyGeneric <T>{
    //使用泛型创建变量
    T t;//可以创建变量,不能实例化对象

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

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


//测试类
package com.collection.list.demo;

public class TestGeneric {
    public static void main(String[] args) {
        //泛型类的使用
        System.out.println("-----泛型类的使用-----");
        MyGeneric<String> myGeneric = new MyGeneric<>();
        myGeneric.show("hello");

        MyGeneric<Integer> myGeneric1 = new MyGeneric<>();
        myGeneric1.show(100);
        
        //注意:1.泛型只能使用引用类型;
        //2.不同泛型类型对象之间不能相互赋值。
    }
}

泛型接口

package com.collection.list.demo;

public interface MyInterface <T>{
    //定义一个泛型接口
    String name = "alice";
    //不能T t;因为接口中只能定义公共静态常量

    T server (T t);
}

对于上述接口有两种使用方法

方法一

package com.collection.list.demo;

public class MyInterfaceImpl implements MyInterface<String> {
    //泛型接口的第一种使用
    //实现类直接确定泛型T的类型
    public String server(String s) {
        System.out.println(s);
        return s;
    }
}


//其测试类
package com.collection.list.demo;

public class TestGeneric {
    public static void main(String[] args) {
        //泛型接口的第一种使用
        System.out.println("-----泛型接口的第一种使用-----");
        MyInterfaceImpl impl = new MyInterfaceImpl();
        impl.server("hello world");
    }
}

方法二

package com.collection.list.demo;

public class MyInterfaceImpl2 <T> implements MyInterface<T>{
    //泛型接口的第二种使用方法
    //实现类不直接指明泛型T的类型
    public T server (T t) {
        System.out.println(t);
        return t;
    }
}



//其测试类
package com.collection.list.demo;

public class TestGeneric {
    public static void main(String[] args) {
        //泛型接口的第二种使用
        System.out.println("-----泛型接口的第二种使用-----");
        MyInterfaceImpl2<String> impl2 = new MyInterfaceImpl2<>();
        impl2.server("java");

        MyInterfaceImpl2<Integer> impl3 = new MyInterfaceImpl2<>();
        impl3.server(100);
    }
}

泛型方法

package com.collection.list.demo;

public class MyGenericMethod {
    public <T> T show(T t) {
        System.out.println(t);
        return t;
    }
}



//测试类
package com.collection.list.demo;

public class TestGeneric {
    public static void main(String[] args) {
        //泛型方法的使用
        System.out.println("-----泛型方法的使用-----");
        MyGenericMethod method = new MyGenericMethod();
        method.show("String");
        method.show(100);//泛型类型由方法参数决定
    }
}

泛型集合

避免类型转换异常

//例如
ArrayList <String> arrayList = new ArrayList<String>();//第二个String可以省略

Set接口

特点

无序、无下标、不可重复

方法

全部继承Collection接口的方法

实例

package com.collection.set;

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

/**
 * set接口的使用
 * 特点:无序,无下标,不可重复
 * 方法:全部继承collection中的方法
 */
public class Demo01 {
    public static void main(String[] args) {
        //set接口的使用
        //创建集合
        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.遍历元素
        //2.1通过增强for遍历
        System.out.println("-----通过增强for遍历-----");
        for (String s : set) {
            System.out.println(s);
        }

        //2.2通过迭代器遍历
        System.out.println("-----通过迭代器遍历-----");
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

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

        //4.删除元素
        set.remove("小米");
        System.out.println("元素个数:"+set.size());

        set.clear();
        System.out.println("元素个数:"+set.size());
    }
}

Set接口的实现类

HashSet类

  1. 存储结构:哈希表(数组+链表+红黑树);
  2. 基于HashCode实现元素不重复;
  3. 当存入元素的哈希码相同时,会调用equals()方法进行确认,如为true则拒绝后者存入。

TreeSet类

  1. 基于排列顺序实现元素不重复;
  2. 实现了SortedSet接口,对集合元素自动排序;
  3. 元素对象的类型必须实现Comparable接口,指定排序规则,否则出现ClassCastException;
  4. 通过comparaTo()方法确定是否为重复元素(自己创建的类要自己实现上一条的接口,重写comparaTo()方法);
  5. 存储结构:红黑树

HashSet

存储过程

  1. 根据HashCode计算要保存的位置,若此位置为空,直接保存,不为空执行第二步;
  2. 执行equals()方法,如果equals()方法为true,则认为重复,否则,形成链表。

实例一

package com.collection.set;

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

/**
 * HashSet的使用一
 * 基于HashCode实现元素不重复
 * 无序、无下标、元素不重复
 * 存储结构:哈希表(数组+链表+红黑树)
 */
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        HashSet<String> hashSet = new HashSet<>();

        //1.添加元素
        hashSet.add("张杰");
        hashSet.add("尊龙");
        hashSet.add("古天乐");
        System.out.println("元素个数:"+hashSet.size());
        System.out.println(hashSet);

        //2.遍历元素
        //2.1增强for
        System.out.println("-----增强for遍历-----");
        for (String s : hashSet) {
            System.out.println(s);
        }

        //2.2迭代器
        System.out.println("-----迭代器-----");
        Iterator<String> it = hashSet.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        //3.判断
        System.out.println(hashSet.contains("张杰"));
        System.out.println(hashSet.isEmpty());

        //4.删除元素
        hashSet.remove("张杰");
        System.out.println("元素个数:"+hashSet.size());
        hashSet.clear();//清空
    }
}

实例二

自定义Person类(TreeSet的实例中也用到了该类,下面不再重复)
package com.collection.set;

import java.util.Objects;

public class Person implements Comparable<Person> {//实现该接口,是用TreeSet存储时必须要做的
    private String name;
    private int age;

    public Person() {
    }

    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) {//重写equals()
        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() {//重写hashCode()
        int n1 = this.name.hashCode();
        int n2 = this.age+31;//+31是因为31是一个质数,减少散列冲突,提高执行效率(系统自动重写时会在这里+31)
        return n1 + n2;
    }

    @Override
    public int compareTo(Person o) {//重写compareTo()
        int n1 = this.name.compareTo(o.getName());
        int n2 = this.age - o.getAge();

        return n1==0?n2:n1;
    }
}

实例二的测试类

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) {
        Person p1 = new Person("刘洪",20);
        Person p2 = new Person("李芳",23);
        Person p3 = new Person("赵亮",19);

        //1.创建集合
        HashSet<Person> hashSet = new HashSet<>();
        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);
        System.out.println("元素个数:"+hashSet.size());

        //2.遍历元素
        //2.1通过增强for
        System.out.println("-----增强for-----");
        for (Person person : hashSet) {
            System.out.println(person);
        }

        //2.2通过迭代器
        System.out.println("-----迭代器-----");
        Iterator<Person> it = hashSet.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        //3.判断
        System.out.println(hashSet.contains(p1));
        System.out.println(hashSet.isEmpty());

        //4.删除元素
        hashSet.remove(new Person("刘洪",20));//重写了equals和hashCode方法,因此此处可以删除
        System.out.println("元素个数:"+hashSet.size());
    }
}

TreeSet

实例一

package com.collection.set;

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

/**
 * TreeSet的使用一
 * 存储结构:红黑树
 * 实现了SortedSet接口,对集合元素自动排序
 */
public class Demo04 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<String> treeSet = new TreeSet<>();

        //1.添加元素
        treeSet.add("hello");
        treeSet.add("world");
        treeSet.add("java");
        System.out.println("元素个数:"+treeSet.size());
        System.out.println(treeSet);

        //2.遍历元素
        //2.1增强for
        System.out.println("-----增强for-----");
        for (String s : treeSet) {
            System.out.println(s);
        }

        //2.2迭代器
        System.out.println("------迭代器-----");
        Iterator<String> it = treeSet.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        System.out.println("-----------------");
        //3.判断
        System.out.println(treeSet.contains("hello"));
        System.out.println(treeSet.isEmpty());

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

    }
}

实例二(Person类在前面)

package com.collection.set;

import java.util.TreeSet;

/**
 * TreeSet的使用二
 * 要求:元素必须实现Comparable接口,compareTo()方法返回值为0时则认为是重复元素
 */
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<Person> personTreeSet = new TreeSet<>();
        //Person类要实现Comparable接口,否则添加元素时出现ClassCastException

        //1.添加元素
        Person p1 = new Person("刘洪",20);
        Person p2 = new Person("李芳",23);
        Person p3 = new Person("赵亮",19);
        personTreeSet.add(p1);
        personTreeSet.add(p2);
        personTreeSet.add(p3);
        System.out.println("元素个数:"+personTreeSet.size());
        System.out.println(personTreeSet.toString());

        //2.遍历元素,两种方法

        //3.判断

        //4.删除元素
        personTreeSet.remove(new Person("赵亮",19));//这样也可以删除,因为是通过compareTo()比较元素是否重复
        System.out.println(personTreeSet);
    }
}

实例三:Comparator接口实现定制比较

package com.collection.set;

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

/**
 * Comparator接口:实现定制比较(比较器)
 */
public class Demo06 {
    public static void main(String[] args) {
        Person p1 = new Person("刘洪",20);
        Person p2 = new Person("李芳",23);
        Person p3 = new Person("赵亮",19);

        //创建集合时就制定比较规则
        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;
            }
        });

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        System.out.println("元素个数:"+persons.size());
        System.out.println(persons.toString());
    }
}

实例四:通过Comparator比较器实现将字符串按照长度大小排序放入集合

package com.collection.set;

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

/**
 * TreeSet案例
 * 将字符串按照长度大小排序放入集合
 * 通过Comparator比较器实现
 */
public class Demo07 {
    public static void main(String[] args) {
        //创建集合并制定比较规则
        TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1 = o1.length() - o2.length();
                int n2 = o1.compareTo(o2);
                return n1==0?n2:n1;
            }
        });

        treeSet.add("abc");
        treeSet.add("xyz");
        treeSet.add("hello");
        treeSet.add("world");
        treeSet.add("java");
        treeSet.add("javac");
        treeSet.add("yours");
        System.out.println(treeSet);
    }
}

Map接口

特点

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

实例

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<String,String> map = new HashMap<>();

        //1.添加元素
        map.put("apple","苹果");
        map.put("banana","香蕉");
        map.put("mango","芒果");//如果key重复,则会覆盖之前添加的元素
        System.out.println("元素个数:"+map.size());
        System.out.println(map);

        //2.遍历元素
        //2.1通过keySet()方法
        System.out.println("-----keySet()方法-----");
        //Set<String> set = map.keySet();
        for (String s : map.keySet()) {
            System.out.println(s+"="+map.get(s));
        }

        //2.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());
        }

        //3.判断
        System.out.println(map.containsKey("apple"));
        System.out.println(map.containsValue("梨子"));
        System.out.println(map.isEmpty());

        //4.删除
        map.remove("apple");
        System.out.println("元素个数:"+map.size());
        System.out.println(map);
    }
}

Map接口的实现类

HashMap类

  1. 线程不安全,运行效率快;允许用null作为key/value;

  2. 存储结构:哈希表(数组+链表+红黑树);

  3. 使用key值的hashCode和equals()判断重复;

  4. 默认容量为10.

  5. 对HashMap源码分析总结

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

HashTable类

  1. 线程安全,效率慢,不允许null作为key/value;
  2. 子类:Properties,要求key和value都是String类型,通常用于配置文件的读取;
  3. 现在这个类不常用了。

TreeMap类

  1. 实现了SortedMap接口,可以对key自动排序;
  2. 存储结构:红黑树;
  3. 要求:key要实现Comparable接口,compareTo()返回为0时认为是重复元素;
  4. 可以定制比较器Comparator接口,创建集合时定制比较规则;
  5. TreeSet实际是用TreeMap的key保存数据。

HashMap

实例

下面例子中会用到的Student类

package com.collection.map;

import java.util.Objects;

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 == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return stuNo == student.stuNo && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return this.stuNo;
    }
}

测试类

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) {
        //创建学生对象
        Student s1 = new Student("张三",101);
        Student s2 = new Student("李四",102);
        Student s3 = new Student("王五",103);

        //创建集合
        HashMap<Student,String> students = new HashMap<>();

        //1.添加元素
        students.put(s1,"上海");
        students.put(s2,"北京");
        students.put(s3,"上海");
        //students.put(new Student("王五",103),"上海");
        System.out.println("元素个数:"+students.size());
        System.out.println(students);

        //2.遍历元素
        //2.1keySet()方法
        System.out.println("-----keySet()方法-----");
        for (Student student:students.keySet()) {
            System.out.println(student+"="+students.get(student));
        }

        //2.2entrySet()方法
        System.out.println("-----entrySet()方法-----");
        for (Map.Entry<Student,String> entry:students.entrySet()) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }

        //3.判断
        System.out.println(students.containsKey(new Student("王五",103)));
        System.out.println("深圳");

        //4.删除
        students.remove(s1);
        System.out.println("元素个数:"+students.size());
    }
}

TreeMap

实例

package com.collection.map;

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

/**
 * TreeMap的使用
 * 存储结构:红黑树
 * 要求:key要实现Comparable接口,compareTo()返回为0时认为是重复元素
 * 如果没有实现该接口也可以自己通过Comparator接口定制比较器
 */
public class Demo03 {
    public static void main(String[] args) {
        Student s1 = new Student("张三",101);
        Student s2 = new Student("李四",102);
        Student s3 = new Student("王五",103);

        //通过比较器实现比较
        TreeMap<Student,String> students = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getStuNo() - o2.getStuNo();
            }
        });

        //1.添加元素
        students.put(s1,"上海");
        students.put(s2,"北京");
        students.put(s3,"南京");
        System.out.println("元素个数:"+students.size());
        System.out.println(students);

        //2.遍历元素
        //2.1keySet()方法
        System.out.println("------keySet()方法--------");
        for (Student student:students.keySet()) {
            System.out.println(student+"="+students.get(student));
        }

        //2.2entrySet()方法
        System.out.println("------entrySet()方法--------");
        for (Map.Entry<Student,String> entry:students.entrySet()) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }

        //3.判断
        System.out.println(students.containsKey(s1));

        //4.删除元素
        students.remove(s1);
        System.out.println("元素个数:"+students.size());
    }
}

Collections工具类

概念

集合工具类,定义了除存储之外的集合常用方法

常用方法

  • public static void reverse(List<?> list) 反转集合中的元素
  • public static void shuffle(List<?> list) 随机重置集合元素的顺序
  • public static void sort(List<?> list) 升序排序(元素类型必须实现Comparable接口)
  • binarySearch(…) 排序之后可进行二分查找
  • copy()复制

实例

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(10);
        list.add(30);
        list.add(70);
        list.add(1);
        list.add(8);
        list.add(100);
        list.add(13);
        System.out.println("排序之前:");
        System.out.println(list);

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

        //binarySearch()排序后可以通过该方法进行二分查找
        int n = Collections.binarySearch(list,1);
        System.out.println("1的下标:"+n);

        //copy()复制,必须先保证两个集合的长度一样
        List<Integer> list1 = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            list1.add(i);
        }
        Collections.copy(list1,list);
        System.out.println(list1);

        //reverse()反转集合
        Collections.reverse(list);
        System.out.println(list);

        //shuffle()打乱
        Collections.shuffle(list);
        System.out.println(list);

        //补充:list-->数组
        Integer[] arr = list.toArray(new Integer[10]);
        System.out.println("数组长度"+arr.length);
        System.out.println(Arrays.toString(arr));

        //数组-->集合
        //转成的集合是一个受限集合,不能增加和删除元素
        String[] arr1 = {"张三","李四","王五","刘英"};
        List<String> list2 = Arrays.asList(arr1);
        System.out.println(list2);
        //list2.add("liu");  UnsupportedOperationException
        //list2.remove("张三"); UnsupportedOperationException

        //基本类型的数组转成集合时要用包装类,装箱
        Integer[] nums = {12,22,30,39};
        List<Integer> list3 = Arrays.asList(nums);
        System.out.println(list3);

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值