【Java开发语言 07】第七章 集合(Java集合概述+Collectionu接口+Iterator接口+Set+List+Map+Collections 工具类)

目录

Java集合概述

在这里插入图片描述

Set

HashSet

特点:

  • 不保证元素的排列顺序

  • 存储的元素不可重复

  • 一个HashSet对象可以存储不同类型的元素

  • 元素可以是null,表示空

  • 不线程安全
    在这里插入图片描述
    在这里插入图片描述

  • HashSet用法

  • 可以存储多种不同类型元素,有排序

  • 由结果可知,不会存放重复元素,null重复是因为一个是空一个是字符串,可以存放空指针null,对象也不是按照添加顺序排序

    • Set set2 = new HashSet();
    • Set set4 = new HashSet();//使用HashSet
    • set1.add(99);//添加元素
    • System.out.println(set1);//打印集合
    • set1.remove(1);//移除元素1
    • System.out.println(set1.contains(“a”));//判断是否包含元素a
    • set1.clear();//清空集合
    • set.size()输出集合长度
 		Set set2 = new HashSet();
        set2.add("a");
        set2.add("b");
        set2.add("c");
        set2.add("d");
        System.out.println(set2);
System.out.println(set2.size());//4
 public static void main(String[] arghs){
        Set set1 = new HashSet();//Set引用类型接收HashSet对象
        set1.add(99);//添加元素
        set1.add(3);
        set1.add(1);
        set1.add("bb");
        set1.add(2);
        set1.add(4);
        set1.add("a");
        set1.add("a");
        set1.add(null);
        set1.add("null");
        System.out.println(set1);

        set1.remove(1);//移除元素
        System.out.println(set1);

        System.out.println(set1.contains("a"));//判断是否包含元素a
        set1.clear();//清空集合
        System.out.println(set1);
    }

在这里插入图片描述

使用迭代器Iterator遍历集合HashSet,for each迭代集合

在这里插入图片描述

在这里插入图片描述

  • 使用Iterator接口遍历集合,使用foreach遍历
  • 这两种都是只能遍历,不能更改内容
  • Iterator it = set2.iterator();
  • while(it.hasNext()){System.out.print(it.next()+" "); }
//Iterator
        Set set2 = new HashSet();
        set2.add("a");
        set2.add("b");
        set2.add("c");
        set2.add("d");//set集合存的值是不重复
        System.out.println(set2);

        //使用迭代器遍历集合
        Iterator it = set2.iterator();

        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }
        System.out.println();

        //for each迭代集合
        for(Object obj : set2){//把set2的每一个值取出来,赋值给obj,直到循环set的所有值
            System.out.print(obj+" ");
        }

在这里插入图片描述

  • HashSet指定类型存储
  • Set<Object> set5 = new HashSet<Object>();
  • 指定String为集合的泛型,这个集合不能存String之外的数据类型,只能存String类
 		Set set3 = new HashSet();
        Set<String> set4 = new HashSet<String>();//指定String为集合的泛型,这个集合不能存String之外的数据类型,只能存String类
        String s1 = "7";
        String s2 = "uyjsdas";
        set4.add(s1);
        set4.add(s2);
        set4.add("");
        set4.add(null);
        set4.add("haha");
        set4.add("中国");
//        set4.add(8);
        System.out.println(set4);

在这里插入图片描述

  • 指定Object,只能存对象,但是基本数据类型也可以储存,因为每一种基本数据类型都是转化为对应的引用类型然后存储 (没有意义,集合本来就只能存引用对象)
//对象类型的HashSet
        Set<Object>set5 = new HashSet<Object>();
        set5.add(new Test());
        set5.add(new A());
        set5.add(7);
        set5.add("iut");
        System.out.println(set5);

在这里插入图片描述

hashcode()方法

在这里插入图片描述

TreeSet

特点:

  • 存入元素时,自动排序存储
  • 只能存一种数据类型,不指定泛型时,按照集合内存储的第一个元素的类型为标准
  • 两种排序方法:1.自然排序 2.定制排序
    在这里插入图片描述
    在这里插入图片描述
  • TreeSet用法
  • TreeSet不能存储重复元素,自然排序从小到大,只能存储一种类型的元素
    • Set set6 = new TreeSet();
    • Set set8 = new TreeSet(new Person());//使用TreeSet
    • set6.add(5);//添加元素
    • System.out.println(set6);//打印集合
    • set6.remove(5);//移除元素5
    • System.out.println(set6.contains(5));//元素5是否存在在集合中
    • set8.clear();//清空集合
 //TreeSet
        //TreeSet
        Set<Integer> set6 = new TreeSet<Integer>();

        set6.add(5);
        set6.add(98);
        set6.add(5);
        set6.add(0);
        System.out.println(set6);
        set6.remove(5);
        System.out.println(set6);
        System.out.println(set6.contains(5));

在这里插入图片描述
注:TreeSet不指定类型的情况下,只能存一种类型的元素。但是HashSet可以存储各种不同基本数据类型的元素

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

不指定List的泛型时,按照已经存储的第一位元素类型为标准

  • 存储过数据之后删除,也不会确定List的泛型,还是按照有存储的第一位元素的类型为这个List对象的泛型标准
  //  TreeSet不定义类型时,只能存一种数据类型,重复数据不存
        Set set7 = new TreeSet();
        set7.add(7);
        set7.remove(7);
        set7.add("fgr");
        set7.remove("fgr");
//        set7.add("oiu7");
//        set7.add("i");
//        set7.add("i");
        set7.add(true);

        System.out.println(set7);

在这里插入图片描述

使用迭代器Iterator遍历集合TreeSet,for each迭代集合

  • for each只能输出不能更改
//使用迭代器Iterator遍历集合
        Iterator<Integer> it2 = set6.iterator();
        while(it2.hasNext()){
            System.out.print(it2.next()+",");//0,78,98,897,
        }
        System.out.println();
        //使用foreach遍历集合
        for(Integer i :set6){
            System.out.print(i+",");//0,78,98,897,
        }

★定制排序

  • 两种定制排序对比
  • 其中compareTo方法可以直接使用在是不是Interger,Character,Double,Float,Long,Short,Byte这七种除过Boolean类型的,基本数据类型的包装类还有String(个人理解)
    在这里插入图片描述
继承接口Comparable重写其方法 public int compareTo(E o)
  • 也称自然排序(未重写的自然排序遵循的是字典排序)
  • compareTo()方法(1.参数为基本数据类型返回-1,0,1+2.参数为String类返回的值小于0,0,大于0)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

继承接口Comparator,重写其方法public int compare(E o1,E o2)
  • 也称比较器(1.与自然排序的定制一样,在自定义类中重写比较器。new集合时参数提供"new E()" 2.如果是一个普通类,则在new集合时参数提供"new Comparetor < E > 对象,并在其中重写比较器",定制排序)
    在这里插入图片描述

  • 定义Person类的排序方式,定制Person类存入的自然排序,使按照年龄从小到大排序

  • Persdon实现Comparator<Person> 抽象类,实现其中的抽象方法public int compare(Person o1, Person o2) ;

  • compare方法中定义return 1则认为o1 > o2排序为o2,o1,return -1o1 < o2return 0o1 == o2。且整体由小到大排序
    在这里插入图片描述

  • 定义Person类,定制比较方法

import java.util.Comparator;

public class Person implements Comparator<Person> {//把Person对象存到TreeSet中并且按照年龄排序
     public Person(){
     }
     public Person(String name, int age){
         this.name = name;
         this.age = age;
     }


    String name;
    int age;

    /**
    * @Description: 定义比较大小方式
    * @Param: [o1, o2]
    * @return: int
    * @Author: xuexuezi
    * @Date: 2022/9/8
    */
    @Override
    public int compare(Person o1, Person o2) {//年龄正序排列
        //return 0;
        if(o1.age > o2.age){
            return 1;
        }else if(o1.age < o2.age){
            return -1;
        }else{
            return 0;
        }
    }

    public void showInfo(){
        System.out.println("姓名:"+this.name+"年龄:"+this.age);
    }
}

  • foreach遍历存Person的集合TreeSet
//Set<Person> set8 = new TreeSet<Person>();错误
        Set<Person> set8 = new TreeSet<Person>(new Person());
        set8.add(p1);
        set8.add(p2);
        set8.add(p3);
        set8.add(p4);
        System.out.println(set8);
        //[com.qx.day10.Person@2db0f6b2, com.qx.day10.Person@3cd1f1c8, com.qx.day10.Person@3a4afd8d, com.qx.day10.Person@1996cd68]

        for(Person p: set8){
            System.out.println(p.name+" "+p.age);
        }

在这里插入图片描述

  • 年龄倒序排序,则使o1.age<o2.age时return 1,此时依旧认为o1>o2,将o1排在o2之后
    • 改写Person类中的compare方法
@Override
public int compare(Person o1, Person o2){//年龄倒序排列
	if(o1.age > o2.age){
		return -1;//认为o1<o2,o2排在后
	}else if(o1.age < o2.age){
		return 1;
	}else{
	return 0;
	}
}

在这里插入图片描述
注:

  • 发现定制排序中一个缺陷,无法存放年龄相同的人,认定o1和o2相等return 0 的情况下,TreeSet中只存一个。
  • 理解为通过年龄排序,年龄即为key值,不能重复存放。但该对象的姓名之类的属性都可以随意相同
 		Person p1 = new Person("张三",9);
        Person p2 = new Person("李四",9);
        Person p3 = new Person("王五",67);
        Person p4 = new Person("赵六",24);

        //Set<Person> set8 = new TreeSet<Person>();
        Set<Person> set8 = new TreeSet<Person>(new Person());
        set8.add(p1);
        set8.add(p2);
        set8.add(p3);
        set8.add(p4);
        //System.out.println(set8);
        //[com.qx.day10.Person@2db0f6b2, com.qx.day10.Person@3cd1f1c8, com.qx.day10.Person@3a4afd8d, com.qx.day10.Person@1996cd68]

        for(Person p: set8){
            System.out.println(p.name+" "+p.age);
        }

在这里插入图片描述

  • 对比普通数据类型,数据本身即为key,相同情况也是不重复保存
		Set set7 = new TreeSet();
        set7.add(7);
        set7.add(98);
        set7.add(98);
        System.out.println(set7);

在这里插入图片描述

两种定制排序对比+自由改写理解(例如比较方法compare只返回1……)

自然排序与比较器排序对比
  • 准备存储的三种不同类型的自定义类
    • Student类,以属性id决定大小,实现自然排序
public class Student implements Comparable<Student>{
    //学生,三个属性,姓名,年龄,学号
    private String name;
    private int age;
    private int id;

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

    }

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

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

    public int getId(){
        return this.id;
    }

    //学号不会重复,所以以学号来决定大小
    @Override
    public int compareTo(Student o) {//o代表当前添加进来需要排序的元素,this代表集合中所有已经排序完成的元素
        if(this.id > o.id){
            return 1;//默认this大于o,o在前,this在后
        }else if(this.id < o.id){
            return -1;
        }else{
            return 0;
        }
        //return 0;
    }

    @Override
    public String toString() {
        //return super.toString();
        return getClass().getName()+"[id="+id+",name="+name+",age="+age+"]";
    }
}

//Student类继承接口Comparable<E>,实现方法compareTo(E o)
        Student stu1 = new Student(2026,"学生1",15);
        Student stu2 = new Student(2022,"学生2",23);
        Student stu3 = new Student(2020,"学生3",35);
 //1.自然排序的自定义类Student
         //TreeSet
        Set<Student> set1 = new TreeSet<>();
        set1.add(stu1);
        set1.add(stu2);
        set1.add(stu3);
        System.out.println(set1);


        //TreeMap
        Map<Student,Integer> map1 = new TreeMap<>();
        map1.put(stu1,23);
        map1.put(stu2,24);
        map1.put(stu3,45);
        System.out.println(map1);
  • 运行结果如下
实现自然排序自定义类的TreeSet[com.qx.javaTest.Student[id=2020,name=学生3,age=35], com.qx.javaTest.Student[id=2022,name=学生2,age=23], com.qx.javaTest.Student[id=2026,name=学生1,age=15]]
实现自然排序自定义类的TreeMap{com.qx.javaTest.Student[id=2020,name=学生3,age=35]=45, com.qx.javaTest.Student[id=2022,name=学生2,age=23]=24, com.qx.javaTest.Student[id=2026,name=学生1,age=15]=23}
    • MyData类,以属性data1决定大小,实现比较器
package com.qx.day10;

import java.util.Comparator;

public class MyData implements Comparator<MyData> {
    public MyData(){

    }
    public MyData(int data1,String name, int data2){

        this.data1 = data1;
        this.name = name;
        this.data2 = data2;
    }


    private String name;
    private int data1;
    private int data2;

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

    public void setData1(int data1){
        this.data1 = data1;
    }
    public int getData1(){
        return data1;
    }

    public void setData2(int data2){
        this.data2 = data2;
    }
    public int getData2(){
        return data2;
    }

    @Override
    public int compare(MyData o1, MyData o2) {//理解新添加需要排序的元素是o1,已经排好序的元素s为o2
        if(o1.data2 > o2.data2){
            return 1;//默认,o1>o2,o2在前,o1在后
        }else if(o1.data2 < o2.data2){
            return -1;默认,o1<o2,o1在前,o2在后
        }
        else{
            return 0;//相等
        }

        //添加顺序1,3,2,4.
       //return 0;//1
        //return 1;//1,3,2,4
        //return -1;//4,2,3,1
        //返回-1,默认o1<o2,o1排在o2之前
    }

    @Override
    public String toString() {
        //return super.toString();
        return getClass().getName()+"[data1="+data1+",name="+name+",data2="+data2+"]";
    }
}

		//MyData类继承接口Comparator<E>,实现方法compare(E o1, E o2)
        MyData d1 = new MyData(34,"数据1",56);
        MyData d2 = new MyData(45,"数据2",6778);
        MyData d3 = new MyData(23,"数据3",908);
//2.比较器排序的自定义类MyData,比较器类型的自定义类需要在new集合的时候提供该类对象作为参数
        //TreeSet
        Set<MyData> set2 = new TreeSet<>(new MyData());
        set2.add(d1);
        set2.add(d2);
        set2.add(d3);
        System.out.println("实现比较器排序的自定义类的TreeSet"+set2);

        //TreeMap
        Map<MyData,Student> map2 = new TreeMap<>(new MyData());
        map2.put(d1,stu1);
        map2.put(d2,stu2);
        map2.put(d3,stu3);
        System.out.println("实现比较器排序的自定义类的TreeMap"+map2);
  • 运行结果
实现比较器排序的自定义类的TreeSet[com.qx.day10.MyData[data1=34,name=数据1,data2=56], com.qx.day10.MyData[data1=23,name=数据3,data2=908], com.qx.day10.MyData[data1=45,name=数据2,data2=6778]]
实现比较器排序的自定义类的TreeMap{com.qx.day10.MyData[data1=34,name=数据1,data2=56]=com.qx.javaTest.Student[id=2026,name=学生1,age=15], com.qx.day10.MyData[data1=23,name=数据3,data2=908]=com.qx.javaTest.Student[id=2020,name=学生3,age=35], com.qx.day10.MyData[data1=45,name=数据2,data2=6778]=com.qx.javaTest.Student[id=2022,name=学生2,age=23]}
    • Puppy类
public class Puppy {

    private int id;
    private String name;
    
    public Puppy(int id,String name){
        this.name = name;
        this.id = id;
    }

    public int getId(){
        return this.id;
    }
    public void setId(int id){
        this.id = id;
    }

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

    @Override
    public String toString() {
        //return super.toString();
        return getClass().getName()+"[id="+id+",name="+name+"]";
    }

}

 //Puppy类,普通类
         Puppy p1 = new Puppy(8,"边牧");
         Puppy p2 = new Puppy(4,"伯恩山");
         Puppy p3 = new Puppy(3,"萨摩耶");
  • 普通类,在集合new的时候传入比较器匿名对象,重写比较方法定制排序规则
//普通类Puppy,在集合new的时候传入匿名类实现普通自定义类的定制排序方法
        //TreeSet
        //自然排序不能这样写,因为本身就是重写在自定义类中直接使用,不需要传参
//        Set<Puppy> set3 = new TreeSet<>(new Comparable<Puppy>(){
//            @Override
//            public int compareTo(Puppy o) {
//                //return 0;
//
//            }
//        });

        Set<Puppy> set3 = new TreeSet<Puppy>(new Comparator<Puppy>(){
            @Override
            public int compare(Puppy o1, Puppy o2) {
                //return 0;
                if(o1.getId() > o2.getId()){
                    return 1;
                }else if(o1.getId() < o2.getId()){
                    return -1;
                }else{
                    return 0;
                }
            }
        });
        set3.add(p1);
        set3.add(p2);
        set3.add(p3);
        System.out.println("普通自定义类在new TreeMap时传匿名对象重写比较器"+set3);


        //TreeMap,key和value都是自定义类的情况,

        Map<Puppy,MyData> map3 = new TreeMap<>(new Comparator<Puppy>(){
            @Override
            public int compare(Puppy o1, Puppy o2) {
                //return 0;
                if(o1.getId() > o2.getId()){
                    return -1;
                }else if(o1.getId() < o2.getId()){
                    return 1;
                }else{
                    return 0;
                }
            }
        });
        map3.put(p1,d1);
        map3.put(p2,d2);
        map3.put(p3,d3);
        System.out.println("普通自定义类在new TreeMap时传匿名对象重写比较器"+map3);
普通自定义类在new TreeMap时传匿名对象重写比较器[com.qx.javaTest.Puppy[id=3,name=萨摩耶], com.qx.javaTest.Puppy[id=4,name=伯恩山], com.qx.javaTest.Puppy[id=8,name=边牧]]
普通自定义类在new TreeMap时传匿名对象重写比较器{com.qx.javaTest.Puppy[id=8,name=边牧]=com.qx.day10.MyData[data1=34,name=数据1,data2=56], com.qx.javaTest.Puppy[id=4,name=伯恩山]=com.qx.day10.MyData[data1=45,name=数据2,data2=6778], com.qx.javaTest.Puppy[id=3,name=萨摩耶]=com.qx.day10.MyData[data1=23,name=数据3,data2=908]}

(脑洞)自由改写定制排序方法的返回情况(例如始终只return 1)

在方法compareTo(E o)和compare(E o1, E o2)中,比较大小时,this(o2)代表当前准备添加进来需要排序的元素,o(o1)代表集合中所有已经排序完成的元素。

  • return 1 时,默认新添加的this(o2)大于o(o1),方法默认升序排序,o(o1)在前,this(o2)在后
  • return -1 时,默认新添加的this(o2)小于o(o1),方法默认升序排序,this(o2)在前,o(o1)在后。
  • return 0 时,默认this(o2)等于o(o1)
    默认都是升序,要降序可以使this(o2) < o1(o)时,return 1;this(o2)>o(o1),return -1。将排序o1(o)在前this(o2)在后,完成降序排序。

自由改写

  • 假设方法始终只return 1 ,表示的含义则为新添加的this(o2)始终更大,排在后。集合为按照元素的添加顺序存储
  • 假设方法只 return 0,表示所有添加进来的元素都相同,则只有集合为空时能存储一个元素。因为TreeSet和TreeMap的key都不可重复
  • 假设方法只 return -1 ,表示的含义则为新添加的this(o2)始终更小,排在前。集合为按照元素的添加顺序的逆序存储

List

List与ArrayList

特点:

  • 可以存储不同类型的数据
  • 按照元素的添加顺序存储
  • 存储的元素可重复
  • 每个元素都有其对应的顺序索引
  • ArrayList对象只能存储同一类型的元素
    在这里插入图片描述
  • ArrayList用法
  • 可以存储重复元素,按照添加顺序设置元素索引
  • 可以存储不同类型的元素
    • List list1 = new ArrayList();//使用ArrayList
    • list1.add(“b”);//添加元素,第一个添加的元素索引下标0
    • list1.add(1,“iu”);//在指定索引位置1,插入元素"iu"
    • list3.set(3,333);//改索引3位置元素为333
    • System.out.println(list1.get(2));//通过索引来访问指定位置的集合元素
    • list3.remove(0);//移除索引为0的元素
    • list3.remove(“happy”);//移除元素happy
    • System.out.println(list3.indexOf(“Taylor”));//查找元素在集合中第一次出现的索引下标
    • System.out.println( list3.lastIndexOf(555));//查找元素最后一次出现的索引
    • List sublist = list3.subList(4,6);//截取list3索引[4,6)的元素形成一个新集合。接去的时候,包含开始索引,不包含结束时索引
    • System.out.println(list3.size());// 返回集合长度
    • list1.clear();//清除集合
    • System.out.println(list1);//打印集合
		 List<String> list1 = new ArrayList<String>();
        list1.add("b");//索引下标0
        list1.add("ulk");//下标1
        list1.add("hyds");//下标2
        list1.add("jh");//下标3
        list1.add("b");
        list1.add("ulk");
        System.out.println(list1);
        System.out.println(list1.get(2));//通过索引来访问指定位置的集合元素
        list1.add(1,"iu");
        System.out.println(list1);
        list1.clear();

在这里插入图片描述

        List list2 = new ArrayList();
        list2.add("b");
        list2.add(8);
        System.out.println(list2);//[b, 8]
 List list3 = new ArrayList();
        list3.add("iu");
        list3.add("Taylor");
        list3.add('o');
        list3.add(8);
        list3.add(null);
        list3.add("happy");
        list3.add(8);
        list3.add(555);
        list3.add(5,555);
        System.out.println(list3);

        list3.remove(0);//移除索引为0的元素
        System.out.println(list3);
        list3.remove("happy");
        System.out.println(list3);

        System.out.println(list3.indexOf("Taylor"));//查找元素在集合中第一次出现的索引下标
        System.out.println( list3.lastIndexOf(555));//查找元素最后一次出现的索引
        list3.set(3,333);//改索引3位置元素为333
        System.out.println(list3);

        List sublist = list3.subList(4,6);//截取list3索引[4,6)的元素形成一个新集合。接去的时候,包含开始索引,不包含结束时索引
        System.out.println(sublist);

在这里插入图片描述

ArrayList存储自定义类及定制排序

在这里插入图片描述

Map

在这里插入图片描述

在这里插入图片描述

  • HashMap 用法
    • map1.put(“b”,1);//添加数据
    • System.out.println(map1.get(“b”));//根据key取值
    • map1.remove(“c”);//根据key移除键值对
    • System.out.println(map1.containsKey(“h”));//判断当前的map集合是否包含指定的key
    • System.out.println(map1.containsValue(10));//判断当前的map集合是否包含指定的value
    • Set keys = map1.keySet();//获取map集合的key的集合,return Set
    • System.out.println(map1.values());//获取集合的所有value值,return Collection
    • System.out.println(map1.size());//map集合的长度
    • map.replace(“c”,67); 替换 hashMap 中是指定的 key 对应的 value。
    • System.out.println(map1);//打印map
    • map1.clear();//清空集合
 		Map<String, Integer> map1 = new HashMap<String, Integer>();
        map1.put("b",1);//添加数据
        map1.put("c",2);
        map1.put("e",2);
        map1.put("f",8);
        map1.put("h",0);
        System.out.println(map1);

        System.out.println(map1.get("b"));//根据key取值

        map1.remove("c");//根据key移除键值对
        System.out.println(map1);

        System.out.println(map1.size());//map集合的长度

        System.out.println(map1.containsKey("h"));//判断当前的map集合是否包含指定的key

        System.out.println(map1.containsValue(10));//判断当前的map集合是否包含指定的value

        //map1.clear();//清空集合

        Set<String> keys = map1.keySet();//获取map集合的key的集合,return Set<E>

        System.out.println(map1.values());//获取集合的所有value值,return Collection

       //遍历map集合,通过map.keySet();
        for(String key: keys){
            System.out.print(key+"="+map1.get(key)+",");
        }

在这里插入图片描述


  		Set<String> keys = map1.keySet();//获取map集合的key的集合,return Set<E>

        System.out.println(map1.values());//获取集合的所有value值,return Collection
 //遍历1,存kay到set,再根据key取value
 //遍历map集合,通过map.keySet();
        for(String key: keys){
            System.out.print(key+"="+map1.get(key)+",");//b=1,e=2,f=8,h=0,
        }
        System.out.println();

//返回映射的Set视图,直接输出
        Set<Entry<String,Integer>> entrys = map1.entrySet();

        System.out.println(entrys);//[b=1, e=2, f=8, h=0]
//for each输出
        for(Entry<String,Integer> en: entrys){
            System.out.println(en.getKey()+" = "+en.getValue());
        }

在这里插入图片描述

HashMap & Hashtable

在这里插入图片描述

TreeMap

在这里插入图片描述

  • TreeMap用法
    • key不可重复,value可以重复
    • 自动的根据key自然排序是字典排序
		Map<Integer,String> map2 = new TreeMap<Integer,String>();
        map2.put(4,"a");
        map2.put(3,"a");
        map2.put(2,"f");
        //TreeMap的自然排序指字典排序
        System.out.println(map2);
        Map<String,String> map3 = new TreeMap<String,String>();
        map3.put("ui","jh");
        map3.put("u","78");
        map3.put("ui","yh");//key不能重复
        map3.put("hu","nj");
        map3.put("gh","df");
        System.out.println(map3);

在这里插入图片描述

TreeMap定制排序+key或value为自定义的类对象

  • 尝试定义Map,key为PetShop对象表示一家宠物店,value为该店饲养宠物的名称。
    • 定制排序,根据PetShop里养的宠物个数来进行排序
    • 因为按照什么排序就会认定什么是key,所以宠物个数相同的对象无法重复存进TreeMap
    • 定义四个对象,店1饲养8只布偶猫;店2饲养78只边牧;店3饲养7只萨摩耶;店4饲养24只布偶猫
import java.util.Comparator;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: xuexuezi
 * @Date: 2022/09/12/15:19
 * @Description:
 */
public class PetShop implements Comparator<PetShop> {//import java.util.Comparator;
    public PetShop(){

    }
    public PetShop(String shopName,int petNum){
        this.shopName = shopName;
        this.petNum = petNum;
    }
    private int petNum;
    private String shopName;

    public int getPetNum(){
        return this.petNum;
    }
    public void setPetNum(int petNum){
        this.petNum = petNum;
    }

    public void setShopName(String shopName){
        this.shopName = shopName;
    }

    public String getShopName(){
        return this.shopName;
    }

    @Override
    public int compare(PetShop o1, PetShop o2) {
        //return 0;
        if(o1.petNum > o2.petNum){
            return 1;//认为o1>o2,且排序由小到大
        }else if(o1.petNum < o2.petNum){
            return -1;
        }else{
            return 0;
        }


    }
}

注:定义的Map中key或value为自定义的类时,new TreeMap需要有参数,new一下这个类对象

 Map<PetShop,String> map4 = new TreeMap<PetShop,String>(new PetShop());
        PetShop s1 = new PetShop("店1",8);
        PetShop s2 = new PetShop("店2",78);
        PetShop s3 = new PetShop("店3",7);
        PetShop s4 = new PetShop("店4",24);
        map4.put(s1,"布偶猫");
        map4.put(s2,"边牧");
        map4.put(s3,"萨摩耶");
        map4.put(s4,"布偶猫");

        //遍历1
        System.out.println(map4);

        //遍历2
        //存key
        Set<PetShop> keys = map4.keySet();
        for(PetShop k:keys){
            System.out.println(k.getShopName()+"  = "+map4.get(k));
        }


        //遍历3
        Set<Entry<PetShop,String>> entrys = map4.entrySet();

        System.out.println(entrys);

        //遍历4
        for(Entry<PetShop,String> e:entrys ){
            System.out.println(e.getKey().getShopName()+"="+e.getValue());
        }

  • 四种遍历TreeMap的方法
    在这里插入图片描述

关于Map的多种输出方式

构造一个HashMap<Integer,Pet>;构造一个TreeMap<Pet,String>其中Pet为自定义的类,表示我拥有的宠物类型

  • Pet属性:名称,数量,腿的个数

  • Pet方法: getter.setter,compare

  • Pet类实现接口Comparator,并实现方法compare来定义Pet的大小,从而在TreeMap中自然排序

    • 其中用到了compareTo方法来比较String的大小
  • 创建Pet类

import java.util.Comparator;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: xuexuezi
 * @Date: 2022/09/17/3:50
 * @Description:
 */
public class Pet implements Comparator<Pet> {
	//无参构造
 public Pet(){
        
    }
    //有参构造
    public Pet(String name,int num, int legNum){
        this.name = name;
        this.num = num;
        this.legNum = legNum;
    }
    private String name;
    private int num;
    private int legNum;

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

    public int getNum(){
        return this.num;
    }
    public void setNum(int num){
        this.num = num;
    }

    public int getLeg(){
        return this.legNum;
    }

    public void setLeg(int legNum){
        this.legNum = legNum;
    }

	//以名字大小决定宠物大小
  @Override
    public int compare(Pet o1, Pet o2) {
        if(o1.name.compareTo(o2.name) > 0){//指定的数o1.name>参数o2.name,返回正数
            return 1;//得出o1>o2.并排在o2后
        }else if(o1.name.compareTo(o2.name) < 0){//指定的数o1.name<o2.name,返回负数
            return -1;
        }else{//相等返回0
            return 0;
        }
    }

  • 构造一个HashMap<Integer,Pet>的map1
        Pet pet1 = new Pet("边牧",1,4);
        Pet pet2 = new Pet("缅因猫",2,4);
        Pet pet3 = new Pet("鹦鹉",4,2);
        Pet pet4 = new Pet("鲸鱼",1,0);
        Map<Integer,Pet> map1 = new HashMap<Integer,Pet>();//该种宠物养了几只
        map1.put(1,pet1);
        map1.put(23,pet4);
        map1.put(56,pet2);
        map1.put(8,pet2);
        map1.put(2,pet3);
  • 构造一个一个TreeMap<Pet,String>的map2
 //注意,以自定义的类为key时,需要在构造map时
        Map<Pet,String> map2 = new TreeMap<Pet,String>(new Pet());//这类宠物性格特征
        map2.put(pet1,"聪明");
        map2.put(pet2,"温顺");
        map2.put(pet3,"漂亮");
        map2.put(pet4,"孤独");

遍历map

1.直接输出map的映射关系
  • 由于对象直接输出会调用该类的toString方法,因为此处没有重写Object类的toString方法,所以输出对象会输出类名+散列码
//1.直接遍历
        System.out.println(map1);
        System.out.println(map2);

输出结果如下:

{1=com.qx.day10.Pet@27ddd392, 2=com.qx.day10.Pet@19e1023e, 23=com.qx.day10.Pet@7cef4e59, 56=com.qx.day10.Pet@64b8f8f4, 8=com.qx.day10.Pet@64b8f8f4}
{com.qx.day10.Pet@64b8f8f4=温顺, com.qx.day10.Pet@27ddd392=聪明, com.qx.day10.Pet@7cef4e59=孤独, com.qx.day10.Pet@19e1023e=漂亮}

-

  • 解决办法1:重写Object的toString方法后直接输出
  @Override
    public String toString() {
        //return super.toString();
        return getClass().getName()+"[name = "+name+",num = "+num+",legNum = "+legNum+"]";
    }

输出结果如下:

{1=com.qx.day10.Pet[name = 边牧,num = 1,legNum = 4], 2=com.qx.day10.Pet[name = 鹦鹉,num = 4,legNum = 2], 23=com.qx.day10.Pet[name = 鲸鱼,num = 1,legNum = 0], 56=com.qx.day10.Pet[name = 缅因猫,num = 2,legNum = 4], 8=com.qx.day10.Pet[name = 缅因猫,num = 2,legNum = 4]}
{com.qx.day10.Pet[name = 缅因猫,num = 2,legNum = 4]=温顺, com.qx.day10.Pet[name = 边牧,num = 1,legNum = 4]=聪明, com.qx.day10.Pet[name = 鲸鱼,num = 1,legNum = 0]=孤独, com.qx.day10.Pet[name = 鹦鹉,num = 4,legNum = 2]=漂亮}
  • 解决办法2:输出对象时,输出他的标志性属性例如名字
  • 直接输出是自动输出键值对,无法做到
2. 用map.keySet返回key的Set集合;再通过方法map.get(key)获得value
  • 此时因为map1和map2的键值对中都包含对象,所以输出对象.name来代表对象,而不是放任其自动输出散列码
//2.使用map.keySet()方法把所有key存入Set集合,再根据map.get()方法,根据key取到value
        Set<Integer> key1 = map1.keySet();
        for(Integer k1: key1){//此处,key为个数直接输出,vaule为对象,直接输出对象是散列码,最好是输出对象的名称
            System.out.println(k1+" = "+map1.get(k1).name);
        }

        Set<Pet> key2 = map2.keySet();
        for(Pet k2: key2){//此处,key为对象,输出对象的名称比较好
            System.out.println(k2.name+" = "+map2.get(k2));
        }

在这里插入图片描述

3.使用map.entrySet()方法,并使用Entry类的Set集合存放所有键值对(Entry内部类可以接收一个键值对)

1.用entry不是因为写起来简单,而是仅仅需要访问一次set里的所有元素即可
2.如果用上面的keySet(),要先访问所有的表key一次,再用key访问所有value一次,耗时是entry的两倍

  • 导包
import java.util.Map.Entry;

Entry内部类来表示一个映射项,映射项包含Key和Value

//3.遍历3
        Set<Entry<Integer,Pet>> entrys = map1.entrySet();
        System.out.println(entrys);

        Set<Entry<Pet,String>> entryss = map2.entrySet();
        System.out.println(entryss);
  • 输出如下
[1=com.qx.day10.Pet@27ddd392, 2=com.qx.day10.Pet@19e1023e, 23=com.qx.day10.Pet@7cef4e59, 56=com.qx.day10.Pet@64b8f8f4, 8=com.qx.day10.Pet@64b8f8f4]
[com.qx.day10.Pet@64b8f8f4=温顺, com.qx.day10.Pet@27ddd392=聪明, com.qx.day10.Pet@7cef4e59=孤独, com.qx.day10.Pet@19e1023e=漂亮]
4.遍历Entry类型的Set,使用Entry的getKey()和getValue()方法
//4.遍历Entry类型的Set,使用Entry的getKey()和getValue()方法
        for(Entry<Integer,Pet> e: entrys){
            System.out.println(e.getKey()+" = "+ e.getValue().name);
        }
        for(Entry<Pet,String> e: entryss){
            System.out.println(e.getKey().name +" = "+e.getValue());
        }

在这里插入图片描述

5.通过 lambda 表达式使用 forEach()

Lambda 表达式
Lamba的语法格式如下:

(parameters) -> expression
或
(parameters) ->{ statements; }

Lambda 表达式的简单例子:

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

HashMap forEach() 方法
forEach() 方法用于对 HashMap 中的每个映射执行指定的操作。
forEach() 方法的语法为:

hashmap.forEach(BiConsumer<K, V> action)

注: hashmap 是 HashMap 类的一个对象。
action - 要执行的操作
Lambda表达式内k,v随意起名。只是代表map中每个键值对的key和value

  • 遍历5.通过 lambda 表达式使用 forEach()
 		 
        map1.forEach((k,v)->{
            System.out.print(k+"="+v.getName()+" ");
        });
        System.out.println();


        map2.forEach((k,v)->{//Lambda表达式内k,v随意起名。只是代表map中每个键值对的key和value
            System.out.print("key:"+k.getName()+"="+"value:"+v+" ");
        });

在这里插入图片描述

Collection接口的含义

Collection接口是Set和List的父亲接口
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Iterator接口,遍历TreeSet,HashSet,ArrayList

调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。

调用 it.hasNext() 用于检测集合中是否还有元素。

调用 it.remove() 将迭代器返回的元素删除。

使用迭代器Iterator遍历

在这里插入图片描述

  • Iterator遍历HashSet

       //Iterator接口
        Set<String> set1 = new HashSet<String>();
        set1.add("ufo");
        set1.add("jisoo");
        set1.add("lisa");


        Iterator<String> it1 = set1.iterator();
        while(it1.hasNext()){
            String i = it1.next();//每次执行都会返回下一个元素,并更新迭代器状态。如果是第一次执行,就返回第一个元素。
            if(i.compareTo("ufo") == 0){
                it1.remove();//删除迭代器返回的元素,如此时,返回的是==ufo的元素
            }else{
                System.out.println(i+" ");//不能使用it1.next()。因为会跳过当前元素,结果为lisa。正确结果为jisoo  lisa
                //理解这个更新迭代器状态意为,此时返回了第一个元素ufo并删除之后,第二次循环i走到第二个元素“jisoo”,如果输出时再调用一次it1.next()会直接越过i,只返回后一位“lisa”错误
                
            }

        }

在这里插入图片描述

  • Iterator遍历TreeSet
 //TreeSet
        Set<Integer> set2 = new TreeSet<Integer>();
        set2.add(56);
        set2.add(9);
        set2.add(56);
        set2.add(6);
        set2.add(99);
        set2.add(78);
        set2.add(87);
        Iterator<Integer> it2 = set2.iterator();

        while(it2.hasNext()){
            Integer i = it2.next();
            if(i < 60){//删除set2中 < 70的元素
                it2.remove();
            }
        }
        System.out.println(set2);

在这里插入图片描述

  • Iterator遍历ArrayList
 //ArrayList
        List<Character> list = new ArrayList<Character>();
        list.add('y');
        list.add('t');
        list.add('T');
        list.add('k');
        Iterator<Character> it3 = list.iterator();
        while(it3.hasNext()){
            if(it3.next() == 't'){//会删掉t,因为现在在y,但是返回后一位t,删除返回的这一位
                it3.remove();
            }
        }
        System.out.println(list);

在这里插入图片描述

注:remove必须在next方法之后调用,因为删除的就是返回的这一个元素

  • 测试,调用两次next再remove,删除的是remove前最后一次返回的元素
//TreeSet
        Set<Integer> set2 = new TreeSet<Integer>();

        set2.add(9);
        set2.add(56);
        set2.add(6);
        set2.add(99);
        set2.add(78);
        set2.add(87);
        Iterator<Integer> it2 = set2.iterator();

        while(it2.hasNext()){
            System.out.println(it2.next());
            System.out.println(it2.next());

            it2.remove();

        }
        System.out.println(set2);

在这里插入图片描述

★Iterator调用多次出现的问题

  • 调用多次,正常输出
    在这里插入图片描述
  • 循环中调用多次
  • 错误出在,一次循环走两步,而每次进入循环的条件只能判断每次走的第一步是可走的,不越界的。
  • 解决方法:因为循环体条件只判断迭代器是否存在元素,即next()方法返回的这一位元素的后一位是否空,只能判断下一位有。所以循环体内最多一次只走一步即可,走两步会在迭代器总共奇数个元素时越界
    在这里插入图片描述

Collections 工具类

工具:反转,随机排序,自然排序,定制排序,交换(List)

在这里插入图片描述
测试-基本数据类型的包装类,String,自定义类MyData三种元素类型存入集合时,使用这5种工具

  • 自定义类MyData,属性:姓名,数据1,数据2
  • 继承接口Comparator,并实现其比较大小的方法compare;此处用数据1的大小决定MyData的大小
import java.util.Comparator;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: xuexuezi
 * @Date: 2022/09/30/18:15
 * @Description: 自定义类,我的数据类型
 */
public class MyData implements Comparator<MyData> {
    public MyData(){

    }
    public MyData(String name,int data1, int data2){
        this.name = name;
        this.data1 = data1;
        this.data2 = data2;
    }


    private String name;
    private int data1;
    private int data2;

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

    public void setData1(int data1){
        this.data1 = data1;
    }
    public int getData1(){
        return data1;
    }

    public void setData2(int data2){
        this.data2 = data2;
    }
    public int getData2(){
        return data2;
    }

    @Override
    public int compare(MyData o1, MyData o2) {
        if(o1.data1 > o2.data1){
            return 1;
        }else if(o1.data1 < o2.data1){
            return -1;
        }
        else{
            return 0;
        }

    }
}

1. Collections.reverse(List)反转元素顺序

  • List元素为:8种基本数据类型的包装类,此处用Character和Double
    • Integer,Character,Byte,Boolean,Short,Long,Float,Bouble
      注意:集合中元素一定是类的对象,不能存放基本数据类型,而是存放他们的包装类
		List<Character> list = new ArrayList<Character>();
        list.add('r');
        list.add('y');
        list.add('u');
        list.add('h');
        System.out.println(list);
   
//=====此处进行Collections 工具类反转,随机排序,自然排序,定制排序,交换5种测试======
        Collections.reverse(list);
//==========================================================================
   
        System.out.println(list);
        
        List<Double> list0 = new ArrayList<Double>();
        list0.add(7.9);
        list0.add(45.765);
        list0.add(67.9876);
        list0.add(7.0);
        System.out.println(list0);
        
//=====此处进行Collections 工具类反转,随机排序,自然排序,定制排序,交换5种测试======
       Collections.reverse(list0);
//==========================================================================  
      
        System.out.println(list0);

在这里插入图片描述

  • List元素为:String数据类型
 List<String> list1 = new ArrayList<String>();
        list1.add("ty");
        list1.add("gth");
        list1.add("frgg");
        list1.add("haha");
        list1.add("ha");
        System.out.println(list1);
        
//=====此处进行Collections 工具类反转,随机排序,自然排序,定制排序,交换5种测试======
        Collections.reverse(list1);
//==========================================================================

        Collections.reverse(list1);
        System.out.println(list1);

在这里插入图片描述

  • List元素为:自定义类的对象(此处不涉及定制排序,因为List是按照添加元素顺序排序的,按原顺序反转即可)
  • 并且MyData定制排序重写比较器compare时,以属性data1作为比较大小的标准
  		//创建存储自定义类的list
        MyData d1 = new MyData("年,月",20,25);
        MyData d2 = new MyData("时,分",18,31);
        MyData d3 = new MyData("年龄,身高",24,168);
        List<MyData> list2 = new ArrayList<MyData>();
        list2.add(d1);
        list2.add(d3);
        list2.add(d2);
        //用迭代器遍历输出对象的属性
        Iterator<MyData> it = list2.iterator();
        //System.out.println(it.next().getName()+it.next().getName()+it.next().getName());
        while(it.hasNext()){
            MyData i = it.next();//用i记录it.next()因为每调用一次next方法,迭代器都会返回下一位,并不会固定停留在某一位
            System.out.println("name="+i.getName()+"; data1="+i.getData1()+"; data2="+i.getData2());
        }

//=====此处进行Collections 工具类反转,随机排序,自然排序,定制排序,交换5种测试======
        Collections.reverse(list2);
//==========================================================================

        it = list2.iterator();
        while (it.hasNext()) {
            MyData i = it.next();//用i记录it.next()因为每调用一次next方法,迭代器都会返回下一位,并不会固定停留在某一位
            System.out.println("name=" + i.getName() + "; data1=" + i.getData1() + "; data2=" + i.getData2());
        }

在这里插入图片描述

2. Collections.shuffle(List)随机排序,即洗牌,打乱顺序


//=====此处进行Collections 工具类反转,随机排序,自然排序,定制排序,交换5种测试======
       //替换上句反转所在位置即可
//==========================================================================

        //反转
//        Collections.reverse(list);
        //洗牌
        Collections.shuffle(list);

     
        //反转
//        Collections.reverse(list0);
        //洗牌
        Collections.shuffle(list0);
   
        //反转
        //Collections.reverse(list1);
        //洗牌
        Collections.shuffle(list1);
     
        //反转
        //Collections.reverse(list2);
        //洗牌
        Collections.shuffle(list2);

   

  • 洗牌后效果
    在这里插入图片描述

3. Collections.sort(List)根据字典,升序排序。也称自然排序


        //反转
//        Collections.reverse(list);
        //洗牌
        //Collections.shuffle(list);
        //升序排序
        Collections.sort(list);

      
        //反转
//        Collections.reverse(list0);
        //洗牌
        //Collections.shuffle(list0);
        //升序排序
        Collections.sort(list0);
      
        //反转
        //Collections.reverse(list1);
        //洗牌
       // Collections.shuffle(list1);
        //升序排序
        Collections.sort(list1);
      

  • 自然升序排序效果
    在这里插入图片描述
    4. Collections.sort(List,Comparator)根据自定大小排序| list.sort(Comparator)

Collections.sort(list2,new MyData());MyData data = new MyData();Collections.sort(list2,data);调用都可以,第二个参数要传一个自定义类的对象,一般用匿名对象

类名称 对象名 = new 类名称();

每次 new 都相当于开辟了一个新的对象,并开辟了一个新的物理内存空间。如果一个对象只需要使用唯一的一次,就可以使用匿名对象,匿名对象还可以作为实际参数传递。

匿名对象就是没有明确的给出名字的对象,是对象的一种简写形式。一般匿名对象只使用一次,而且匿名对象只在堆内存中开辟空间,而不存在栈内存的引用。

 //创建存储自定义类的list
        MyData d1 = new MyData("年,月",20,25);
        MyData d2 = new MyData("时,分",18,31);
        MyData d3 = new MyData("年龄,身高",24,168);
        List<MyData> list2 = new ArrayList<MyData>();
        list2.add(d1);
        list2.add(d3);
        list2.add(d2);
        //用迭代器遍历输出对象的属性
        Iterator<MyData> it = list2.iterator();
        //System.out.println(it.next().getName()+it.next().getName()+it.next().getName());
        while(it.hasNext()){
            MyData i = it.next();//用i记录it.next()因为每调用一次next方法,迭代器都会返回下一位,并不会固定停留在某一位
            System.out.println("name="+i.getName()+"; data1="+i.getData1()+"; data2="+i.getData2());
        }

        //反转
        //Collections.reverse(list2);
        //洗牌
        //Collections.shuffle(list2);
        //升序排序
        MyData data = new MyData();
        Collections.sort(list2,data);

        it = list2.iterator();
        while (it.hasNext()) {
            MyData i = it.next();//用i记录it.next()因为每调用一次next方法,迭代器都会返回下一位,并不会固定停留在某一位
            System.out.println("name=" + i.getName() + "; data1=" + i.getData1() + "; data2=" + i.getData2());
        }
  • 根据比较器的自定义大小排序
    在这里插入图片描述
  • 直接用 list.sort排序也可以
public static class NodeComp implements Comparator<Node>{
        @Override
        public int compare(Node o1, Node o2) {
            return o1.value - o2.value;
        }
    }
 ArrayList<Node> list = new ArrayList<>();
 list.sort(new NodeComp());//排序list内存储的节点
// 这两个都可以,Collections.sort(list, new NodeComp());

5. swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

  • 注意:int表示要交换的两个元素在list中的下标,不可越界。下标第一个元素从0开始

        //反转
//        Collections.reverse(list);
        //洗牌
        //Collections.shuffle(list);
        //升序排序
//        Collections.sort(list);
        //交换
        Collections.swap(list,0,3);

      
        //反转
//        Collections.reverse(list0);
        //洗牌
        //Collections.shuffle(list0);
        //升序排序
        //Collections.sort(list0);

        //交换
        Collections.swap(list0,0,3);
     
        //反转
        //Collections.reverse(list1);
        //洗牌
       // Collections.shuffle(list1);
        //升序排序
        //Collections.sort(list1);
        //交换
        Collections.swap(list1,0,3);
       
        //反转
        //Collections.reverse(list2);
        //洗牌
        //Collections.shuffle(list2);
        //升序排序
//        MyData data = new MyData();
//        Collections.sort(list2,data);
        //交换
        Collections.swap(list2,0,2);

      
  • 交换结果
    在这里插入图片描述

工具:返回最大值,最小值(分为自然排序和定制排序两种不同的大小判断)返回元素出现次数,新值代替旧值(List,TreeSet,HashSet)

在这里插入图片描述
在这里插入图片描述
关于Collection集合类的继承树如下图,图片转自java集合Collection常用方法详解

在这里插入图片描述

  • 构造所用集合
  • MyData类定义见前上一小标题: 工具:反转,随机排序,自然排序,定制排序,交换(List)
 		MyData d1 = new MyData(20, "年,月", 4);
        MyData d2 = new MyData(18, "时,分", 31);
        MyData d3 = new MyData(24, "年龄,身高", 168);
        MyData d4 = new MyData(168, "身高,体重", 75);

        List<Integer> list1 = new ArrayList<Integer>();
        List<MyData> list2 = new ArrayList<>();

        Set<Character> hset1 = new HashSet<>();
        Set<MyData> hset2 = new HashSet<>();

        Set<Double> tset1 = new TreeSet<>();
        Set<MyData> tset2 = new TreeSet<>();

        list1.add(8);
        list1.add(67);
        list1.add(345);
        list1.add(9);

        list2.add(d1);
        list2.add(d2);
        list2.add(d3);

        hset1.add('a');
        hset1.add('b');
        hset1.add('c');

        hset2.add(d1);
        hset2.add(d2);
        hset2.add(d3);
        
        tset1.add(4.6);
        tset1.add(9.674);
        tset1.add(1.0);
        
        tset2.add(d1);
        tset2.add(d2);
        tset2.add(d3);
  • 创建类Student
public class Student {
    private int id;
    private String name;
    
    public Student(){
        
    }
    
    public Student(int id, String name){
        this.id = id;
        this.name = name;
    }
    
    public void setId(int id){
        this.id = id;
    }
    public int getId(){
        return this.id;
    }
    
    public void setNmae(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
}
  1. Object max(Collection)根据元素的自然顺序,返回给定集合中的最大元素
  • List元素为:8种基本数据类型的包装类和String
    • Integer,Character,Byte,Boolean,Short,Long,Float,Bouble
      注意:集合中元素一定是类的对象,不能存放基本数据类型,而是存放他们的包装类
//1. Object max(Collection)根据元素的自然顺序,返回给定集合中的最大元素

        System.out.println("打印list1,为存储Integer元素的ArrayList"+list1);
        System.out.println("list1的max:"+Collections.max(list1));
打印list1,为存储Integer元素的ArrayList[8, 67, 345, 9]
list1的max:345
  • HashSet元素为:8种基本数据类型的包装类和String
 		System.out.println("打印hset1,为存储Character元素的HashSet"+hset1);
        System.out.println("hset1的max:"+Collections.max(hset1));
打印hset1,为存储Character元素的HashSet[a, b, c]
hset1的max:c
  • TreeSet元素为:8种基本数据类型的包装类和String
 		System.out.println("打印tset1,为存储Double元素的TreeSet"+tset1);
        System.out.println("tset的max:"+Collections.max(tset1));
打印tset1,为存储Double元素的TreeSet[1.0, 4.6, 9.674]
tset的max:9.674
  1. Object max(Collection,Comparator)根据Comparator指定的顺序,返回给定集合中的最大元素
  • List元素为:MyData自定义类对象
    注: 比较器参数的两种写法
 //2.Object max(Collection,Comparator)根据Comparator指定的顺序,返回给定集合中的最大元素
//
        System.out.println("打印list2,为存储MyData元素的ArrayList"+list2);
//        Iterator<MyData> it1 = list2.iterator();
//        while(it1.hasNext()){
//            System.out.print(it1.next()+" ");
//        }
//        System.out.println();
        //写法一:自定义类中有重写比较器
        System.out.println("list2的max的data1:"+Collections.max(list2, new MyData()).getData1());
       
        //写法二:普通类,在参数部分重写
        //本身ArrayList存储的元素是不需要定制排序的,但是这个方法需要
        List<Student> list3 = new ArrayList<Student>();
        list3.add(new Student(01,"张三"));
        list3.add(new Student(02,"李四"));
        list3.add(new Student(03,"王五"));
        System.out.println("打印list3,为存储Student的ArryList"+list3);
        System.out.println("list3的max的id:"+Collections.max(list3,new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //return 0;
                if (o1.getId() > o2.getId()) {
                    return 1;//升序
                } else if (o1.getId() < o2.getId()) {
                    return -1;
                } else {
                    return 0;
                }
            }
        }).getId());
打印list2,为存储MyData元素的ArrayList[com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31], com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168]]
list2的max的data1:24
打印list3,为存储StudentArryList[com.qx.day10.Student[id=1,name=张三], com.qx.day10.Student[id=2,name=李四], com.qx.day10.Student[id=3,name=王五]]
list3的max的id:3

  • HashSet元素为:MyData自定义类对象
		System.out.println("打印hset2,为存储MyData元素的HashSet"+hset2);
        System.out.println("hset2的max的data1:" + Collections.max(hset2, new MyData()).getData1());

        
    
打印hset2,为存储MyData元素的HashSet[com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31]]
hset2的max的data1:24

  • TreeSet元素为:MyData自定义类对象
 		System.out.println("打印tset2,为存储MyData元素的TreeSet"+tset2);
        System.out.println("tset2的max的data1:" + Collections.max(tset2, new MyData()).getData1());
打印tset2,为存储MyData元素的TreeSet[com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31], com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168]]
tset2的max的data1:24
  1. Object min(Collection)根据元素的自然顺序,返回给定集合中的最小元素
  • List元素为:8种基本数据类型的包装类和String
		System.out.println("打印list1,为存储Integer元素的ArrayList" + list1);
        System.out.println("list1的min:" + Collections.min(list1));     
打印list1,为存储Integer元素的ArrayList[8, 67, 345, 9]
list1的min:8
  • HashSet元素为:8种基本数据类型的包装类和String
		System.out.println("打印hset1,为存储Character元素的HashSet" + hset1);
        System.out.println("hset1的min:" + Collections.min(hset1));   
打印hset1,为存储Character元素的HashSet[a, b, c]
hset1的min:a
  • TreeSet元素为:8种基本数据类型的包装类和String
 		System.out.println("打印tset1,为存储Double元素的TreeSet"+tset1);
        System.out.println("tset的min:"+Collections.min(tset1));
打印tset1,为存储Double元素的TreeSet[1.0, 4.6, 9.674]
tset的min:1.0
  1. Object min(Collection, Comparator)根据Comparator指定的顺序,返回给定集合中的最小元素
  • List元素为:MyData自定义类对象
 		System.out.println("打印tset2,为存储MyData元素的TreeSet"+list2);
        System.out.println("list2的min的data1:"+Collections.min(list2, new MyData()).getData1());      
打印tset2,为存储MyData元素的TreeSet[com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31], com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168]]
list2的min的data1:20
  • HashSet元素为:MyData自定义类对象
  		System.out.println("打印hset2,为存储MyData元素的HashSet"+hset2);
        System.out.println("hset2的min的data1:"+Collections.min(hset2,new MyData()).getData1());      
打印hset2,为存储MyData元素的HashSet[com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31]]
hset2的min的data1:20
  • TreeSet元素为:MyData自定义类对象
		System.out.println("打印tset2,为存储MyData元素的TreeSet"+hset2);
        System.out.println("tset2的min的data1:"+Collections.min(tset2,new MyData()).getData1());
打印tset2,为存储MyData元素的TreeSet[com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31]]
tset2的min的data1:20
  1. int frequency(Collection,Object)返回指定集合中指定元素的出现次数
  • List元素为:8种基本数据类型的包装类,此处用Character和Double
		list1.add(96);
        list1.add(96);
        System.out.println("打印list1,为存储Integer元素的ArrayList" + list1);
        System.out.println("list1的96出现次数:" + Collections.frequency(list1,96));
     
打印list1,为存储Integer元素的ArrayList[8, 67, 345, 9, 96, 96]
list1的96出现次数:2

  • HashSet元素为:8种基本数据类型的包装类和String数据类型
    注: HashSet和TreeSet无法存储重复元素 ,所以该方法在这两个集合中只会返回0,1
 		System.out.println("打印hset1,为存储Character元素的HashSet" + hset1);
        System.out.println("hset1的'u:出现次数" + Collections.frequency(hset1,'u'));
打印hset1,为存储Character元素的HashSet[a, b, c]
hset1的'u:出现次数0
  • TreeSet元素为:8种基本数据类型的包装类和String数据类型
        tset1.add(5.8);
        tset1.add(5.8);
        System.out.println("打印tset1,为存储Double元素的TreeSet"+tset1);
        System.out.println("tset的5.8出现次数:"+Collections.frequency(tset1,5.8));
打印tset1,为存储Double元素的TreeSet[1.0, 4.6, 5.8, 9.674]
tset的5.8出现次数:1
  • List元素为:MyData自定义类对象
    发现: 统计出现次数时,要求元素一定是同一个对象,这里的同一个指必须要是这个对象(用get(index)来访问之前有添加的对象,哪怕修改了属性也依然算是这个对象。
    创建两个对象属性都相同也不是同一个对象。
 		list2.add(new MyData(11,"一",78));//index 3
        list2.add(new MyData(11,"呵呵",78));//4
        list2.add(new MyData(11,"一",78));//5
        list2.add(new MyData(11,"一",67));//6
        list2.add(list2.get(3));
        list2.add(list2.get(5));
   		//在下一次添加索引5的对象之前修改他的属性
        list2.get(5).setData1(700);
        list2.add(list2.get(5));
        
        System.out.println("打印list2,为存储MyData元素的TreeSet"+list2);
        System.out.println("list2的new MyData(11,\"一\",78)的出现次数:"+Collections.frequency(list2, new MyData(11,"一",78)));

        System.out.println("list2的list2.get(5)的出现次数"+Collections.frequency(list2,list2.get(5) ));
打印list2,为存储MyData元素的TreeSet[com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31], com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=11,name=呵呵,data2=78], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=11,name=,data2=67], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=11,name=,data2=78]]
list2的new MyData(11,"一",78)的出现次数:0
list2的list2.get(5)的出现次数:3
  • HashSet元素为:MyData自定义类对象
    要查找对象,但是没有索引可以取,只能用max,min取对象
 		hset2.add(Collections.max(hset2,new MyData()));
 		
        System.out.println("打印hset2,为存储MyData元素的HashSet"+hset2);
        System.out.println("hest2的data1的max的出现次数:"+Collections.frequency(hset2, Collections.max(hset2,new MyData())));
打印hset2,为存储MyData元素的HashSet[com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31]]
hest2的data1的max的出现次数:1
  • TreeSet元素为:MyData自定义类对象
    没意义,反正只会返回1或0
		System.out.println("打印tset2,为存储MyData元素的TreeSet"+hset2);
        System.out.println("tset2的new MyData(11,\"一\",78)的出现次数:"+Collections.frequency(tset2, new MyData(11,"一",78)));
打印tset2,为存储MyData元素的TreeSet[com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31]]
tset2的new MyData(11,"一",78)的出现次数:0
  1. boolean replaceAll(List list,Object oldVal,newVal)使用新值代替
  • List元素为:8种基本数据类型的包装类和String数据类型
 list1.add(8);
        list1.add(8);
        list1.add(8);
        System.out.println("打印list1,为存储Integer元素的ArrayList"+list1);
        System.out.println("用888代替8,"+Collections.replaceAll(list1,8,888)+"->"+list1);
打印list1,为存储Integer元素的ArrayList[8, 67, 345, 9, 96, 96, 8, 8, 8]888代替8,true->[888, 67, 345, 9, 96, 96, 888, 888, 888]
  • List元素为:MyData自定义类对象
 list2.add(list2.get(0));
        list2.add(list2.get(0));
        System.out.println("打印list2,为存储MyData元素的ArrayList"+list2);
        System.out.println("用MyData[data1=22,name=年,月,data2=10]代替对象索引为0的MyData[data1=20,name=年,月,data2=4],"+Collections.replaceAll(list2,list2.get(0),new MyData(22,"年,月",10))+"->"+list2);
打印list2,为存储MyData元素的ArrayList[com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=18,name=,,data2=31], com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=11,name=呵呵,data2=78], com.qx.day10.MyData[data1=700,name=,data2=78], com.qx.day10.MyData[data1=11,name=,data2=67], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=700,name=,data2=78], com.qx.day10.MyData[data1=700,name=,data2=78], com.qx.day10.MyData[data1=20,name=年,月,data2=4], com.qx.day10.MyData[data1=20,name=年,月,data2=4]]Disconnected from the target VM, address: '127.0.0.1:4127', transport: 'socket'MyData[data1=22,name=年,月,data2=10]代替对象索引为0MyData[data1=20,name=年,月,data2=4],true->[com.qx.day10.MyData[data1=22,name=年,月,data2=10], com.qx.day10.MyData[data1=18,name=,,data2=31], com.qx.day10.MyData[data1=24,name=年龄,身高,data2=168], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=11,name=呵呵,data2=78], com.qx.day10.MyData[data1=700,name=,data2=78], com.qx.day10.MyData[data1=11,name=,data2=67], com.qx.day10.MyData[data1=11,name=,data2=78], com.qx.day10.MyData[data1=700,name=,data2=78], com.qx.day10.MyData[data1=700,name=,data2=78], com.qx.day10.MyData[data1=22,name=年,月,data2=10], com.qx.day10.MyData[data1=22,name=年,月,data2=10]]

集合练习

编程题

一,map的遍历,插入,删除,替换

一、现在有一个map集合如下:
	HashMap<Integer,String> map = new HashMap<Integer, String>();
			map.put(1, "张三丰");
			map.put(2, "周芷若");
			map.put(3, "汪峰");
			map.put(4, "灭绝师太");
	要求:
	1.遍历集合,并将序号与对应人名打印。
	2.向该map集合中插入一个编码为5姓名为李晓红的信息
	3.移除该map中的编号为1的信息 
	4.将map集合中编号为2的姓名信息修改为"周林"
  • 1.遍历集合,并将序号与对应人名打印。
public static void main(String[] args){

        HashMap<Integer,String> map = new HashMap<Integer,String>();
        map.put(1,"张三丰");
        map.put(2,"周芷若");
        map.put(3,"汪峰");
        map.put(4,"灭绝师太");

        //遍历集合
        //遍历1,直接输出
        System.out.println("遍历1,直接输出");
        System.out.println(map);

        //遍历2,map.keySet返回key的Set集合;再map.get(key)获得value
        System.out.println("遍历2,map.keySet返回key的Set集合;再map.get(key)获得value");
        Set<Integer> key = map.keySet();
        for(Integer k: key){
            System.out.println(k+"="+map.get(k)+" ");
        }
        //遍历3.使用map.entrySet()方法,并使用Entry类的Set集合存放所有键值对
        System.out.println("遍历3.使用map.entrySet()方法,并使用Entry类的Set集合存放所有键值对");
        Set<Entry<Integer,String>> entrys = map.entrySet();
        System.out.println(entrys);

 		//遍历4.遍历Entry类型的Set,使用Entry的getKey()和getValue()方法
        System.out.println("遍历4.遍历Entry类型的Set,使用Entry的getKey()和getValue()方法");
        for(Entry<Integer,String> e:entrys){
            System.out.println(e.getKey()+"="+e.getValue());
        }
      
}

在这里插入图片描述

  • 2.向该map集合中插入一个编码为5姓名为李晓红的信息
        map.put(5,"李晓红");
        System.out.println(map);

在这里插入图片描述

  • 3.移除该map中的编号为1的信息
        map.remove(1);
        System.out.println(map);

在这里插入图片描述

  • 4.将map集合中编号为2的姓名信息修改为"周林"
       map.replace(2,"周林");//替换指定的key对应value
        //map.put(2,"周林");//小技巧,可以直接添加。因为如果key存在,就会替换这个key的value
        System.out.println(map);

在这里插入图片描述
注:只修改value,确认key已经存在的情况下,可以直接使用添加put。key重复的情况下只会刷新value的值

二、根据两个数组元素构造map并遍历

二、有2个数组,第一个数组内容为:[黑龙江省,浙江省,江西省,广东省,福建省],
               第二个数组内容为:[哈尔滨,杭州,南昌,广州,福州],
			   将第一个数组元素作为key,第二个数组元素作为value存储到Map集合中。
			   如{黑龙江省=哈尔滨, 浙江省=杭州, …}。
			   使用两种方式遍历map集合
 String[] arr1 = {"黑龙江省","浙江省","江西省","广东省","福建省"};
        String[] arr2 = {"哈尔滨","杭州","南昌","广州","福州"};

        Map<String,String> map = new TreeMap<>();
        for(int i=0; i<arr1.length && i<arr2.length; i++){
            map.put(arr1[i],arr2[i]);
        }
        //遍历1,直接输出
        System.out.println(map);

        //遍历2,Set存储key
        Set<String> key = map.keySet();
        for(String k:key){
            System.out.println(k+"="+map.get(k));
        }

        //遍历3,entry类
        Set<Entry<String,String>> entrys = map.entrySet();
        System.out.println(entrys);

        //遍历4,entry类foreach
        for(Entry<String,String> e:entrys){
            System.out.println(e);
        }

在这里插入图片描述

三,统计输入字符,每种字符的个数

三、分析以下需求,并用代码实现	
	1.利用键盘录入,输入一个字符串
	2.统计该字符串中各个字符的数量(提示:字符不用排序)
	3.如:
		用户输入字符串"If~you-want~to~change-your_fate_I_think~you~must~come-to-the-dark-horse-to-learn-java"
		程序输出结果:
		-(9)I(2)_(3)a(7)c(2)d(1)e(6)f(2)g(1)h(4)i(1)j(1)k(2)l(1)m(2)n(4)o(8)r(4)s(2)t(8)u(4)v(1)w(1)y(3)~(6)
  • 方法一: 创建一个178大小的数组,因为ASCII码表的范围为0-177,默认赋值全为0。将数组下标作为字符的ASCII码值,每个位置对应的字符出现一次,数组元素就+1。
		BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入字符串");
        String str = "";//空字符串
        try {
            str = buffer.readLine();
        } catch (Exception e) {
            e.printStackTrace();
        }

        char[] arr = str.toCharArray();
        int[] ascii = new int[178];//默认值全为0

        for (int i=0; i < arr.length; i++) {
            //遍历字符数组,检索字符个数
            ascii[arr[i]]++;//每检索到一个字符就在对应位置++

        }

        for(int i=0; i<ascii.length; i++){
            if(ascii[i] != 0){
                System.out.print((char)i+"("+ascii[i]+")");
            }
        }

在这里插入图片描述

  • 方法二: 用Map,每读到一个字符,就作为key存储,value为出现次数,随着读取增加。
    注: 区分统计个数时,字符第一次出现,不可用map3.put(arr4[i],map3.get(arr4[i])+1);因为此时get(key)中key不存在,返回出错
//用Map组建对应关系
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入字符串");
        String str2="";//如果不赋值,因为不确定try中能否成功赋值。toCharArray时字符有空的可能,编译出错。
        try{
            str2 = buf.readLine();
        }catch(Exception e){
            e.printStackTrace();
        }

        //注意到,元素不装箱,依然可以正常将char类型的元素赋值给类型为Character的key
        //因为自动装箱
        char[] arr4 = str2.toCharArray();

//        //将元素装箱
//        char[] arr3 = str2.toCharArray();
//        Character[] arr4 = new Character[arr3.length];
//        for(int i=0; i<arr3.length; i++){
//            arr4[i] = new Character(arr3[i]);
//        }

        //读到字符数组以后,构造Map
        Map<Character,Integer> map3 = new TreeMap<>();
        for(int i=0; i<arr4.length; i++){
            //每读到一个字符就输入,因为key重复的话只刷新value,所以直接put,value++即可
            //如果读到新字符,get(key)将无法获取value,注意区分
            
            if(map3.containsKey(arr4[i])){
                map3.put(arr4[i],map3.get(arr4[i])+1);
            }else{
                map3.put(arr4[i],1);
            }

        }
       
  • char赋值给Character为自动装箱,不需要在进行操作
    在这里插入图片描述
 //map的5种遍历方式
        System.out.println("1.map3直接输出");
        System.out.println(map3);

        System.out.println("2.keySet()方法遍历key+get(key)获得value");
        Set<Character> key3 = map3.keySet();
        for(Character k: key3){
            System.out.print(k+"("+map3.get(k)+")");
        }
        System.out.println();

        System.out.println("3.entry类型接收map的entrySet方法,一个entry类对象相当于一个键值对。直接输出entrySet");
        Set<Entry<Character,Integer>> entrys3= map3.entrySet();
        System.out.println(entrys3);

        System.out.println("4.for each输出entrySet");
        Set<Entry<Character,Integer>> entrys4= map3.entrySet();
        for(Entry<Character,Integer> e:entrys4){
            System.out.print(e.getKey()+"("+e.getValue()+")");
        }
        System.out.println();

        System.out.println("5.Lambde表达式forEach输出");
        map3.forEach((k,v)->{
            System.out.print(k+"("+v+")");
        });

★图片总结集合特征

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值