五、集合基础【黑马JavaSE笔记】

2022-11-23 17:30:15 浏览数 (1)

文章目录
  • 集合
    • (一)集合基础
      • 1.集合概述
      • 2.ArrayList构造方法和添加方法
      • 3.ArrayList集合常用方法
      • 4.遍历集合的通用格式
    • (二)Collection
      • 1.集合类体系结构
      • 2.Collection集合概述和使用
      • 3.Collection集合常用方法
      • 4.Collection集合的遍历
      • 5.集合的使用步骤
      • 6.案例(Collection集合存储学生对象并遍历)
    • (三)List集合
      • 1.List集合概述和特点
      • 2.List集合特有方法
      • 3.案例(List集合存储学生对象并遍历)
      • 4.并发修改异常
      • 5.ListIterator列表迭代器
      • 6.增强for循环
      • 7.案例(List集合存储学生对象用三种方式遍历)
      • 8.List 集合子类特点
      • 9.案例(分别使用ArrayList和LinkedList完成存储字符串并遍历)
      • 10.LinkedList集合的特有功能
    • (四)Set集合
      • 1.Set集合概述和特点
      • 2.哈希值
      • 3.HashSet集合概述和特点
      • 4.HashSet集合保证元素唯一性源码分析
      • 5.案例(HashSet集合存储学生对象并遍历)
      • 6.LinkedHashSet集合概述和特点
      • 7.TreeSet集合概述和特点
      • 8.自然排序Comparable的使用
      • 9.比较器排序Comparator的使用
      • 10.案例(不重复的随机数)
    • (五)Map集合
      • 1.Map集合概述和使用
      • 2.Map集合的基本功能
      • 3.Map集合的获取功能
      • 4.Map集合的遍历
        • (1)方式一
        • (2)方式二
      • 5.案例(HashMap嵌套ArrayList)
      • 6.统计字符串中每个字符出现的次数
    • (六)Collections工具类
      • 1.Collections概述和使用

集合

(一)集合基础

1.集合概述

集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以发生改变

集合类有很多种,ArrayList是其中的一种

ArrayList:

  • 可调整大小的数组实现
  • :是一种特殊的数据类型,泛型

如何用?

  • 在出现E的地方使用引用数据类型替换即可
  • 举例:ArrayList,ArrayList

2.ArrayList构造方法和添加方法
  • public ArrayList() 创建一个空的集合对象
  • public boolean add(E e) 将指定的元素追加到此集合的末尾(因为调用这个方法的返回值是boolean类型,也就是调用完毕后会返回一个true或者false
  • public void add(int index,E element) 在此集合中的指定位置插入指定的元素

代码演示:

代码语言:javascript复制
//	public boolean add(E e)
ArrayList<String> array = new ArrayList<>();
array.add("hello");
array.add("Java");
System.out.println(array);  //[hello, Java]
System.out.println(array.add("world")); // true

//	public void add(int index,E element) 
array.add(1,"Javase");
System.out.println(array);  // [hello, Javase, Java]
array.add(4,"1111");    //IndexOutOfBoundsException(索引越界)

3.ArrayList集合常用方法
  • public boolean remove(Object to) 删除指定的元素,返回删除是否成功
  • public E remove(int index) 删除指定索引处的元素,返回被删除的元素
  • public E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
  • public E get(int index) 返回指定索引处的元素
  • public int size() 返回集合中的元素个数

代码演示:

代码语言:javascript复制
//	public boolean remove(Object to)	返回删除是否成功
System.out.println(array.remove("Javase")); //true
System.out.println(array.remove("111"));    //false
//	public E remove(int index)  返回被删除的元素
System.out.println(array.remove(1));    //Java
//	public E set(int index,E element) 返回被修改的元素
System.out.println(array.set(0,"hello1"));  //hello
//	public E get(int index) 	返回指定索引处的元素
System.out.println(array.get(0));   //hello1
//	public int size()  	返回集合中元素的个数
System.out.println(array.size());   //1

4.遍历集合的通用格式
代码语言:javascript复制
ArrayList<String> array = new ArrayList<>();
        array.add("hello");
        array.add("java");
        array.add("world");
//  遍历集合的通用格式
 for (int i = 0; i < array.size(); i  ) {
            String s = array.get(i);
            System.out.println(s);
 }

(二)Collection

1.集合类体系结构
2.Collection集合概述和使用

Collection集合概述

  • 是单例集合的顶层接口,他表示一组对象,这些对象也称为Collection的元素
  • JDK不提供此接口的任何直接实现,它提供更具体的子接口(如set和List)实现

创建Collection集合的对象

  • 多态的方式
  • 具体的实现类ArrayList

代码演示:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {
    public static void main(String[] args) {
        //创建Collection集合对象
        Collection<String> c = new ArrayList<>();
        //添加元素:boolean add(E e)
        c.add("hello");
        c.add("world");
        c.add("java");
        //输出集合对象
        System.out.println(c);// [hello, world, java]
    }
}

3.Collection集合常用方法
4.Collection集合的遍历

Iterator:迭代器,集合的专用遍历格式

  • Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
  • 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的

Iterator中的常用方法

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true

代码演示:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo {
    public static void main(String[] args) {
        //创建Collection集合对象
        Collection<String> c = new ArrayList<>();
        c.add("hello");
        c.add("world");
        c.add("java");
        System.out.println(c);  //[hello, world, java]
        //通过集合的 Iterator<E> iterator()方法获得迭代器对象
        Iterator<String> i = c.iterator();//多态的方式获得对象 (在iterator方法里返回了实现类对象)
        //用while循环遍历集合
        while(i.hasNext()){
            String s = i.next();
            System.out.println(s);
        }
    }
}
/*
public Iterator<E> iterator() {
        return new Itr();
    }

private class Itr implements Iterator<E> {
	......
}
*/

5.集合的使用步骤

6.案例(Collection集合存储学生对象并遍历)

代码实现:

创建学生类(Student):

代码语言:javascript复制
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;
    }
}

创建测试类(StudentDemo):

代码语言:javascript复制
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class StudentDemo {
    public static void main(String[] args) {
        //创建集合对象
        Collection<Student> c = new ArrayList<>();
        //创建三个学生对象
        Student s1 = new Student("学生1",20);
        Student s2 = new Student("学生2",21);
        Student s3 = new Student("学生3",22);
        //将学生对象添加进集合中存储
        c.add(s1);
        c.add(s2);
        c.add(s3);
        //通过集合对象的方法获得迭代器对象
        Iterator<Student> i = c.iterator();
        //遍历集合
        while(i.hasNext()) {
            Student s = i.next();
            System.out.println(s.getName() ", " s.getAge());
        }
    }
}


(三)List集合

1.List集合概述和特点
  • 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
  • 与Set集合不同,列表通常允许重复的元素

List集合特点

  • 有序:存储和取出的元素顺序一致
  • 可重复:存储的元素可以重复

代码演示:

代码语言:javascript复制
public class ListDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");

        //获取迭代器(因为List集合继承自Collection集合,所以Collection集合有的方法,List集合也有)
        Iterator<String> it = list.iterator();
        //用迭代器的方式遍历List集合
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
    }
}

2.List集合特有方法

注:以上方法时List集合特有的方法,Collection集合没有这些方法,但是ArrayLIst集合有这些方法,因为ArrayList继承自List集合。

  • List集合不仅可以通过迭代器的方式进行遍历集合,也可以用for循环的方式遍历

代码实现:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.List;

public class ListDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");

        //for循环遍历集合
        for (int i = 0; i < list.size(); i  ) {
            String s = list.get(i);
            System.out.println(s);
        }
    }
}

3.案例(List集合存储学生对象并遍历)

创建学生类(省略,具体参考Collection案例)

创建测试类(ListDemo):

代码语言:javascript复制
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo {
    public static void main(String[] args) {
        //创建List对象
        List<Student> list = new ArrayList<>();
        //创建三个学生对象
        Student s1 = new Student("学生1", 20);
        Student s2 = new Student("学生2", 21);
        Student s3 = new Student("学生3", 22);

        //将学生对象放入List集合中存储
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //遍历List集合(两种方式:for循环和迭代器)
        //for循环遍历
        for (int i = 0; i < list.size(); i  ) {
            Student s = list.get(i);
            System.out.println(s.getName()   ", "   s.getAge());
        }

        //迭代器遍历
        Iterator<Student> it = list.iterator();
        while(it.hasNext()){
            Student s = it.next();
            System.out.println(s.getName() ", " s.getAge());
        }

    }
}

4.并发修改异常
  • ConcurrentModificationException

产生原因

  • 迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致

解决方案

  • 用for循环遍历,然后用集合对象做对应的操作即可
代码语言:javascript复制
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        /*
        //迭代器
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            if(s.equals("java")){
                list.add("javaee");//ConcurrentModificationException(并发修改异常)
            }
        }
        */
        //用for循环解决并发修改异常
        
        for (int i = 0; i < list.size(); i  ) {
            String s = list.get(i);
            if(s.equals("java")){
                list.add("javaee");
            }
        }

        System.out.println(list);//[hello, java, world, javaee]
    }
}
/*add方法源码
 public boolean add(E e) {
        modCount  ;	实际修改集合的次数   与 预期修改集合的次数不符(exceptedModeCount)
        add(e, elementData, size);
        return true;
    }
 */
//使用get方法内部就不会有上述两个变量(modCount和exceptedModeCount)的比较

5.ListIterator列表迭代器
  • 通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器
  • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

ListIterator中的常用方法

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true
  • E previous():返回列表中的上一个元素
  • boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
  • void add(E e):将指定的元素插入列表

代码演示:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorDemo {
    public static void main(String[] args) {
        //创建List集合
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        //创建List迭代器
        ListIterator<String> lit = list.listIterator();
        while(lit.hasNext()){
            String s = lit.next();
            if(s.equals("java")){
                lit.add("javaee");//此时不会出现并发修改异常,因为底层代码将实际修改集合的次数赋值给了预期修改集合的次数(exceptedModeCount = modCount)
            }
        }
    }
}

6.增强for循环
  • 实现Iterator接口的类允许其对象成为增强型for语句的目标
  • 它是JDK5之后出现的,其内部原理是一个Iterator迭代器

增强for格式

格式:

for(元素数据类型 变量名:数组或者Collection集合){

​ //在此处使用变量即可,该变量就是元素

}

范例:

代码语言:javascript复制
int[] arr = {1,2,3,4,5};
for(int i : arr) {
	System.out.println(i)
}

7.案例(List集合存储学生对象用三种方式遍历)

创建学生对象(省略,具体参考前面):

创建测试类:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class forDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<Student> list = new ArrayList<>();
        //创建三个学生对象
        Student s1 = new Student("学生1", 20);
        Student s2 = new Student("学生2", 21);
        Student s3 = new Student("学生3", 22);

        //将学生对象存入集合中
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //普通for循环遍历List集合
        for (int i = 0; i < list.size(); i  ) {
            Student s = list.get(i);
            System.out.println(s.getName()   ", "   s.getAge());
        }

        //list迭代器遍历List集合
        ListIterator<Student> lit = list.listIterator();
        while (lit.hasNext()) {
            Student s = lit.next();
            System.out.println(s.getName()   ", "   s.getAge());
        }

        //增强for循环遍历
        for(Student i : list){
            System.out.println(i.getName() ", " i.getAge());
        }
    }
}

8.List 集合子类特点

List 集合常用子类:ArrayList,LinkedList

  • ArrayList:底层数据结构是数组,查询快,增删慢
  • LinkedList:底层数据结构式链表。查询慢,增删快

9.案例(分别使用ArrayList和LinkedList完成存储字符串并遍历)

代码实现:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;

public class ArrayListDemo {
    public static void main(String[] args) {
        //1.ArrayList集合遍历
        ArrayList<String> array = new ArrayList<>();
        array.add("hello");
        array.add("world");
        array.add("java");

        //普通for循环遍历
        for (int i = 0; i < array.size(); i  ) {
            String s = array.get(i);
            System.out.println(s);
        }

        //迭代器遍历
        ListIterator<String> lit = array.listIterator();
        while (lit.hasNext()) {
            String s2 = lit.next();
            System.out.println(s2);
        }

        //增强for循环遍历
        for (String s3 : array) {
            System.out.println(s3);
        }


        //2.LinkedList集合遍历
        LinkedList<String> link = new LinkedList<>();
        link.add("hello");
        link.add("world");
        link.add("java");

        //普通for循环
        for (int i = 0; i < link.size(); i  ) {
            String s = link.get(i);
            System.out.println(s);
        }

        //迭代器
        ListIterator<String> lit2 = link.listIterator();
        while (lit2.hasNext()) {
            String s2 = lit2.next();
            System.out.println(s2);
        }

        //增强for循环遍历
        for (String s3 : link) {
            System.out.println(s3);
        }
    }
}

10.LinkedList集合的特有功能

(四)Set集合

1.Set集合概述和特点

Set集合特点

  • 不包含重复元素的集合
  • 没有带索引的方法,所以不能使用普通for循环

Set集合练习

  • 存储字符串并遍历
代码语言:javascript复制
import java.util.HashSet;
import java.util.Set;

public class SetDemo {
    public static void main(String[] args) {
        //创建集合对象
        Set<String> set = new HashSet<>();//HashSet对集合的迭代顺序不作任何保证

        //添加元素
        set.add("hello");
        set.add("java");
        set.add("world");
        //不包含重复元素
        set.add("world");//结果只有一个world

        //遍历集合
        for (String s : set) {
            System.out.println(s);
        }
    }
}

2.哈希值

哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

Object类中有一个方法可以获取对象的哈希值

  • public int hashCode():返回对象的哈希码值

对象的哈希值特点

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

3.HashSet集合概述和特点

HashSet集合特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以是不包含重复元素的集合

HashSet集合练习

  • 存储字符串并遍历
代码语言:javascript复制
import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<String> sh = new HashSet<>();
        sh.add("hello");
        sh.add("world");
        sh.add("java");

        //迭代器遍历
        Iterator<String> it = sh.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

        //增强for遍历
        for(String s : sh){
            System.out.println(s);
        }

    }
}

4.HashSet集合保证元素唯一性源码分析

HashSet集合添加一个元素过程:

HashSet集合存储元素:

  • 要保证元素唯一性,需要重写hashCode()和equals()
5.案例(HashSet集合存储学生对象并遍历)

要求:学生对象的成员变量值相同,我们就认为是同一个对象

代码实现:

创建学生类(需要重写hashCode()和equals()方法来保证元素的唯一性)

代码语言:javascript复制
import java.util.Objects;

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

    public Student() {

    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    //重写重写hashCode()和equals()方法来保证元素的唯一性
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

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

创建测试类

代码语言:javascript复制
import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<Student> sh = new HashSet<>();
        Student s1 = new Student("学生1", 20);
        Student s2 = new Student("学生2", 21);
        Student s3 = new Student("学生3", 22);
        Student s4 = new Student("学生1",20);//与s1相同

        sh.add(s1);
        sh.add(s2);
        sh.add(s3);
        sh.add(s4);//结果并未显示s4,因为与s1位同一个元素,在学生类定义中重写了hashCode()和equals()方法确保了元素的唯一性

        //迭代器遍历集合
        Iterator<Student> it = sh.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName()   ", "   s.getAge());
        }

        //增强for遍历集合
        for(Student s : sh) {
            System.out.println(s.getName()   ", "   s.getAge());
        }
    }
}

6.LinkedHashSet集合概述和特点

LinkedHashSet集合特点

  • 哈希表和链表实现的Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,也就是 说元素的存储和取出顺序是一致的
  • 由哈希表保证元素唯一,也就是说没有重复的元素

LinkedHashSet集合练习

  • 存储字符串并遍历
代码语言:javascript复制
import java.util.LinkedHashSet;

public class LinkedHashSetDemo {
    public static void main(String[] args) {
        //LinkedHashSet集合保证了元素的唯一性也保证了存储和取出的顺序的一致性
        LinkedHashSet<String> lh = new LinkedHashSet<>();
        lh.add("hello");
        lh.add("java");
        lh.add("world");

        lh.add("hello");//元素唯一性,所以结果不显示多余的hello字符串
        for (String s : lh) {
            System.out.println(s);
        }
    }
}

7.TreeSet集合概述和特点

TreeSet集合特点

  • 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法 ​ TreeSet():根据其元素的自然排序进行排序 ​ TreeSet(Comparetor comparator):根据指定的比较器进行排序
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以不包含重复元素

TreeSet集合练习

  • 存储整数并遍历
代码语言:javascript复制
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<>();
        //添加元素
        ts.add(2);
        ts.add(3);
        ts.add(1);

        //因为它是Set集合,所以不包含重复元素
        ts.add(2);

        for(Integer it: ts) {
            System.out.print(it);//结果为 1 2 3
        }
    }
}

8.自然排序Comparable的使用
  • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
  • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

练习:

  • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法
  • 要求:按照年龄从小到大牌,年龄相同时,按照姓名的字母顺序排序

代码实现:

定义学生类:

代码语言:javascript复制
public class Student implements Comparable<Student> {
    private String name;
    private int 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;
    }

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

    @Override
    public int compareTo(Student s) {
//        return -1;//降序
//        return 0;//元素重复
//        return 1;//升序

        int flag = this.age - s.age;    //this在前为升序,在后为降序
        int flag2 = flag == 0 ? this.name.compareTo(s.name) : flag;		//String类自带compareTo方法
        return flag2;
    }
}

创建测试类:

代码语言:javascript复制
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<>();
        Student s1 = new Student("学生1",22);
        Student s2 = new Student("学生2",23);
        Student s3 = new Student("学生3",33);

        Student s4 = new Student("学生4",33);

        Student s5 = new Student("学生4",33);
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);//s5与s4元素重复所以结果不显示

        for(Student s:ts) {
            System.out.println(s.getName() ", " s.getAge());
        }
    }
}

9.比较器排序Comparator的使用
  • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
  • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要和次要条件来写

练习:

  • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

代码实现

定义一个标准的学生类:(此处省略)

定义测试类:

代码语言:javascript复制
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int flag = s1.getAge() - s2.getAge();
                int flag2 = flag == 0 ? s1.getName().compareTo(s2.getName()) : flag;
                return flag2;
            }
        });

        Student s1 = new Student("学生1",22);
        Student s2 = new Student("学生2",23);
        Student s3 = new Student("学生3",33);

        Student s4 = new Student("学生4",33);

        Student s5 = new Student("学生4",33);
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);//s5与s4元素重复所以结果不显示

        for(Student s:ts) {
            System.out.println(s.getName() ", " s.getAge());
        }
    }
}

分析:

这里o1表示位于前面的对象,o2表示后面的对象

  • 返回-1(或负数),表示不需要交换01和02的位置,o1排在o2前面,asc
  • 返回1(或正数),表示需要交换01和02的位置,o1排在o2后面,desc

下面来用我们之前的结论解释为什么 return o2.a - o1.a 就是降序了:

首先o2是第二个元素,o1是第一个元素。无非就以下这些情况: ①: o2.a > o1.a: 那么此时返回正数,表示需要调整o1,o2的顺序,也就是需要把o2放到o1前面,这不就是降序了么。

②:o2.a < o1.a : 那么此时返回负数,表示不需要调整,也就是此时o1 比 o2大, 不还是降序么。


10.案例(不重复的随机数)

编写一个程序,获取10个1~20之间的随机数,要求随机数不能重复,并在控制台输出

代码语言:javascript复制
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

public class SetDemo {
    public static void main(String[] args) {
        //创建集合对象
        //Set<Integer> set = new HashSet<>();//HashSet集合是无序且元素唯一
        Set<Integer> set = new TreeSet<>();//TreeSet集合是有序且元素唯一

        //创建随机数对象
        Random r = new Random();

        //判断集合的长度是否小于10
        while (set.size() < 10) {
            int sum = r.nextInt(20)   1;
            set.add(sum);
        }

        for(Integer i :set) {
            System.out.println(i);
        }
    }
}

(五)Map集合

1.Map集合概述和使用

Map集合概述

  • interface Map<K,V> K:键的类型; V:值的类型
  • 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
  • 举例:学生的学号和姓名

创建Map集合的对象

  • 多态的方式
  • 具体的实现类HashMap

代码演示:

代码语言:javascript复制
import java.util.HashMap;
import java.util.Map;

public class MapDemo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        //V put (K key,V value) 将指定的值与该映射中的指定键相关联
        map.put("19103205", "学生1");
        map.put("19103206", "学生2");
        map.put("19103204", "学生3");
        map.put("19103204", "学生4");//第二次使用put方法相当于修改

        //输出集合对象
        System.out.println(map);//{19103206=学生2, 19103204=学生4, 19103205=学生1}
    }
}

2.Map集合的基本功能

3.Map集合的获取功能

代码演示:

代码语言:javascript复制
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        //V put (K key,V value) 将指定的值与该映射中的指定键相关联
        map.put("19103205", "学生1");
        map.put("19103206", "学生2");
        map.put("19103204", "学生3");

        // V get(Object key):根据键获取值
        System.out.println(map.get("19103205"));//学生1
        System.out.println(map.get("191032"));//null

        //Set<K> keySet():获取所有键的集合
        Set<String> set = map.keySet();
        for(String i : set){
            System.out.println(i);
        }

        //Collection<V> values():获取所有值的集合
        Collection<String> collection = map.values();
        for(String i :collection) {
            System.out.println(i);
        }
    }
}

4.Map集合的遍历
(1)方式一

遍历思路:

  • 获取所有键的集合。用keySet()方法实现
  • 遍历键的集合,获取到每一个键。用增强for实现
  • 根据键去找值。用get(Object key)方法实现

代码演示:

代码语言:javascript复制
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        //添加
        map.put("19103205", "学生1");
        map.put("19103206", "学生2");
        map.put("19103204", "学生3");
        
        //遍历
        Set<String> keySet = map.keySet();
        //遍历键的集合,获取到每一个键
        for (String key : keySet) {
            //根据键去找值
            String value = map.get(key);
            System.out.println(key   ","   value);
        }
    }
}
(2)方式二

遍历思路:

  • 获取所有键值对对象的集合 ​ Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
  • 遍历键值对对象的集合,得到每一个键值对对象 ​ 用增强for实现,得到每一个Map.Entry
  • 根据键值对对象获取键和值 ​ 用getKey()得到键 ​ 用getValue()得到值

代码演示:

代码语言:javascript复制
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        //添加
        map.put("19103205", "学生1");
        map.put("19103206", "学生2");
        map.put("19103204", "学生3");

        //遍历
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for (Map.Entry<String, String> me : entrySet) {
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key   ","   value);
        }
    }
}

5.案例(HashMap嵌套ArrayList)
代码语言:javascript复制
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class HashMapDemo2 {
    public static void main(String[] args) {
        //创建HashMap集合
        HashMap<String, ArrayList<String>> hm = new HashMap<>();
        //创建ArrayList集合,并添加元素
        ArrayList<String> sgyy = new ArrayList<>();
        sgyy.add("诸葛亮");
        sgyy.add("赵云");
        //将ArrayList作为元素添加到集合中
        hm.put("三国演义", sgyy);

        ArrayList<String> xyj = new ArrayList<>();
        xyj.add("唐僧");
        xyj.add("孙悟空");
        hm.put("西游记", xyj);

        ArrayList<String> shz = new ArrayList<>();
        shz.add("武松");
        shz.add("鲁智深");
        hm.put("水浒传", shz);

        //遍历
        Set<String> keySet = hm.keySet();
        for (String key : keySet) {
            System.out.println(key);
            ArrayList<String> value = hm.get(key);
            for (String array : value) {
                System.out.print(array ", ");
            }
            System.out.println();
        }
    }
}

6.统计字符串中每个字符出现的次数

代码实现:

代码语言:javascript复制
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

public class HashMapDemo3 {
    public static void main(String[] args) {
        //创建HashMap集合(无顺序)
        //HashMap<Character, Integer> hm = new HashMap<>();
        //创建TreeMap集合(可以有顺序)
        TreeMap<Character, Integer> hm = new TreeMap<>();
        //键盘录入
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一组字符串:");
        String s = sc.nextLine();
        //遍历字符串
        for (int i = 0; i < s.length(); i  ) {
            //获取到每一个字符
            char key = s.charAt(i);
            //将字符作为键值到HashMap中进行比较,看返回结果
            Integer value = hm.get(key);
            if (value == null) {//如果返回结果为空,则表示这是第一个存储进去的元素
                hm.put(key, 1);
            } else {    //如果结果不为空,则说明集合中存在这个键及元素,所以数量(value)加1
                value  ;
                hm.put(key, value);//将新的键和值重新添加
            }
        }
        //遍历HashMap集合,得到键和值,按要求进行拼接
        StringBuilder sb = new StringBuilder();

        Set<Character> keySet = hm.keySet();
        for (Character key : keySet) {
            Integer value = hm.get(key);
            sb.append(key).append("(").append(value).append(")");
        }

        //将StringBuilder类型转为String类型
        String result = sb.toString();
        //输出结果
        System.out.print(result);
    }
}

(六)Collections工具类

1.Collections概述和使用

Collections类的概述

  • 是针对集合操作的工具类

Collections类的常用方法

代码演示:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsDemo {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();

        list.add(20);
        list.add(10);
        list.add(40);
        list.add(50);
        list.add(30);

        //将指定的序列按升序排列
        Collections.sort(list);
        //将指定的序列反转
        Collections.reverse(list);
        //使用默认的随机源随机排列指定的元素
        Collections.shuffle(list);

        System.out.println(list);
    }
}

0 人点赞