2021.2.1java集合框架2

JAVA集合框架2

四.泛型和工具类

1.泛型的基本概念

  • 泛型其本质是参数化类型,把类型作为参数传递
  • 常见的形式有泛型类、泛型接口、泛型方法
  • 语法:<T,....>T称为占位符,表示一种引用类型,如果编写多个需要用逗号隔开
  • 好处1:提高代码的重用性(能执行很多类型的数据
  • 好处2:防止类型转换异常,提高代码的安全性

2.泛型的基本运用

  1. 泛型类
//泛型类
public class G<T> {
//使用泛型T
    //不能利用利用 T 进行实例化,不能new
    //T这个数据类型并不知道,他的构造方法不一定有无参构造
       //1.创建变量
     public T t;
       //2.泛型作为方法的参数
    public void setT(T t) { this.t=t; }
        //3. 泛型作为方法的返回值
    public T getT(){
        return t;
        }
}
public class Test {
   //1.泛型只能使用引用类型
    //2.不同的泛型类型对象之间不能互相赋值
    public static void main(String[] args) {
            G<String> g1 = new G<String>();
            g1.t = "hello";
        System.out.println(g1.t);
            g1.setT("girl!");
        System.out.println(g1.getT());

            G<Integer> g2 = new G<Integer>();
            g2.t = 110;
        System.out.println(g2.t);
            g2.setT(120);
        System.out.println(g2.getT());

            G<String> g3 = g1;
            //G<String> g4=g2;报错
        }
}
/*结果:
hello
girl!
110
120
*/
  1. 泛型接口
//泛型接口
//语法:接口名<T,E,...>
//T是类型占位符,表示一种引用类型,如果编写多个可以使用逗号隔开
public interface G2<T> {
    //接口中定义的所有变量都是常量,隐藏public static final
    //但是注意!!!不能定义!!!泛型常量!!!定义常量时必须先初始化,而T的类型并不知道,不能new,无法初始化------->T t;编译出错
    String name="lyj";
    //接口中定义的所有方法都是 public abstract
    T add (T t);
    //参数是T类型,返回值也是T

}
//泛型接口G2的实现类G2Impl
//需要写好泛型的类型
public class G2Impl implements G2<String>{
    @Override
    public String add(String s) {
        return s;
    }
}
//泛型接口G2的实现类G2Impl
//可以不写好泛型的类型
public class G2Impl2<T> implements G2<T>{
    @Override
    public T add(T t) {
        return t;
    }
}
 public static void main(String[] args) {
    G2Impl gg=new G2Impl();
    System.out.println(gg.add("hhhhhh"));
    G2Impl2<Integer> ggg=new G2Impl2<Integer>();
    System.out.println(ggg.add(555));
}
/*结果:
hhhhhh
555
*/
  1. 泛型方法
//泛型方法
//语法:<T> 返回值类型
//使用泛型方法,在执行程序时,需要编辑的类型可以自己把握
public class G3 {
    public <T> void show(T t){
        System.out.println(t);
    }
    public <T>  T show2(T t){
        System.out.println(t);
       return t;
    }
}
 public static void main(String[] args) {    
    G3 g31=new G3();
    g31.show("wawawaawa");//输入什么数据类型的数据,就执行什么类型的数据
    g31.show(1000);
    g31.show2("heiheihei");
    g31.show2(1000.05);
}
/*结果:
wawawaawa
1000
heiheihei
1000.05

*/

使用泛型方法就像使用普通方法一样

3.泛型集合

  • 参数化类型、类型安全的集合,强调集合元素的类型
  • 访问时,不必要类型转换(拆箱)
  • 不同泛型之间引用不能相互赋值,泛型不存在多态
//泛型集合

public class H {
    public static void main(String[] args) {
//利用之前List接口下的ArrayList类创建一个泛型集合
        ArrayList<String> arrayList1 = new ArrayList<String>();
        arrayList1.add("lyj");
        // arrayList1.add(111);报错
        arrayList1.add("zyx");//应用了泛型集合,类型是什么,只能添加什么类型的数据

        //遍历集合,使用增强for,不会出现类型转换的问题,此处的数据都是一种类型
        for (String s : arrayList1) {
            System.out.println(s.toString());
        }
//泛型集合的类型也可以是自己定义的类
        ArrayList<Student> arrayList2 = new ArrayList<Student>();
        Student s1 = new Student("aaa", 5);
        Student s2 = new Student("bbb", 10);
        Student s3 = new Student("ccc", 15);
        Student s4 = new Student("ddd", 20);
        arrayList2.add(s1);
        arrayList2.add(s2);
        arrayList2.add(s3);
        arrayList2.add(s4);
        //arrayList2.add("xxx");报错
        //遍历集合,利用迭代器,不会出现类型转换的问题,此处的数据都是一种类型
        Iterator<Student> it = arrayList2.iterator();
        while (it.hasNext()) {
            Student student = it.next();
            System.out.println(student.toString());
        }
    }
}
/*结果:
lyj
zyx
name:aaa age:5
name:bbb age:10
name:ccc age:15
name:ddd age:20
*/

五.Set接口与实现类

1.Set子接口

  • 特点:无序、无下标、元素不可重复
  • 方法:全部继承自Collection中的方法

2.Set接口的使用

//Set接口的使用
//特点:1.无序,没有下标 2.不能重复
public class I {
    public static void main(String[] args) {
//创建集合,接口不能实例化,但是能创建对象;需要利用实现类
        Set<String> set1 = new HashSet<String>();
//1.添加元素
        set1.add("aaa");
        set1.add("bbb");
        set1.add("ccc");
        set1.add("bbb");//不能重复添加
        System.out.println("元素个数:" + set1.size());//集合长度(个数)
        System.out.println(set1.toString());//无序的
        System.out.println("====================================");
//2.删除元素
        set1.remove("ccc");//删除不能靠角标
        System.out.println("元素个数:" + set1.size());//集合长度(个数)
        System.out.println(set1.toString());//无序的
        System.out.println("====================================");
        //set1.clear()全部清除
// 3.遍历数据(只能使用增强for和迭代器)
        //1)增强for
        System.out.println("使用增强for来遍历");
        for (String s : set1) {
            System.out.println(s.toString());
        }
        //2)使用迭代器Iterator遍历,迭代器是个接口,方法如下
        //hasNext();判断有没有下一个元素
        //next();获取下一个元素
        //remove();删除当前元素
        System.out.println("使用迭代器Iterator来遍历");
        Iterator<String> it = set1.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s.toString());
        }
            System.out.println("====================================");
//4.判断
            System.out.println(set1.contains("000"));
            System.out.println(set1.isEmpty());
    }
}
/*结果:
元素个数:3
[aaa, ccc, bbb]
====================================
元素个数:2
[aaa, bbb]
====================================
使用增强for来遍历
aaa
bbb
使用迭代器Iterator来遍历
aaa
bbb
====================================
false
false
*/

3.Set接口的实现类

  1. HashSet类

    • 基于HashCode计算元素存放的位置
    • 当存入的元素的哈希码值相同时,会调用equals进行确认,如结果为true,则拒绝后者进入
    • 存储结构:哈希表(数组+链表
     public static void main(String[] args) {
    //新建集合
            HashSet<String> hashSet1=new HashSet<>();//后面<>的类型可以写也可以不写
    //1.添加元素
            hashSet1.add("aaa");
            hashSet1.add("bbb");
            hashSet1.add("ccc");
            hashSet1.add("ddd");
            hashSet1.add("bbb");//不能重复添加
            System.out.println("元素个数:" + hashSet1.size());//集合长度(个数)
            System.out.println(hashSet1.toString());//无序的
            System.out.println("====================================");
    //2.删除元素
            hashSet1.remove("ccc");//删除不能靠角标
            System.out.println("元素个数:" + hashSet1.size());//集合长度(个数)
            System.out.println(hashSet1.toString());//无序的
            System.out.println("====================================");
            //set1.clear()全部清除
    // 3.遍历数据(只能使用增强for和迭代器)
            //1)增强for
            System.out.println("使用增强for来遍历");
            for (String s : hashSet1) {
                System.out.println(s.toString());
            }
            //2)使用迭代器Iterator遍历,迭代器是个接口,方法如下
            //hasNext();判断有没有下一个元素
            //next();获取下一个元素
            //remove();删除当前元素
            System.out.println("使用迭代器Iterator来遍历");
            Iterator<String> it = hashSet1.iterator();
            while (it.hasNext()) {
                String s = it.next();
                System.out.println(s.toString());
            }
            System.out.println("====================================");
    
    //4.判断
            System.out.println(hashSet1.contains("000"));
            System.out.println(hashSet1.isEmpty());
        }
    /*结果
    元素个数:4
    [aaa, ccc, bbb, ddd]
    ====================================
    元素个数:3
    [aaa, bbb, ddd]
    ====================================
    使用增强for来遍历
    aaa
    bbb
    ddd
    使用迭代器Iterator来遍历
    aaa
    bbb
    ddd
    ====================================
    false
    false
    */
    
    //HashSet存储过程
    //1.根据hashCode计算保存的位置,如果位置为空,则直接保存,如果不为空,则执行第2步
    //2.再执行equals方法,如果equals方法为true,则认为重复,不保存,false则形成链表
        public static void main(String[] args) {
            //创建集合
            HashSet<Student> students=new HashSet<>();
    //1.添加元素
            //在Student类中进行有参构造
            Student s1=new Student("aaa",5);
            Student s2=new Student("bbb",10);
            Student s3=new Student("ccc",15);
            Student s4=new Student("ddd",20);
            students.add(s1);
            students.add(s2);
            students.add(s3);
            students.add(s3);//重复,不会添加
            students.add(s4);
            students.add(new Student("ddd",20));//未修改hasdCode、equals方法前是可以添加,修改完添加不了
            System.out.println("元素个数:"+students.size());//集合长度(个数)
            System.out.println(students.toString());//此处的toString方法需要重写
            System.out.println("===================================");
    //2.删除元素
            //删除元素需要用到hasCode()方法找到他的存储位置,再equals()方法进行比较
            //不重写hasCode、equals()方法,没法删除下面(元素相同,对象名不同)的集合元素
            students.remove(new Student("aaa",5));
            System.out.println("元素个数:"+students.size());//集合长度(个数)
            System.out.println(students.toString());
            System.out.println("====================================");
    //3.遍历元素
            //(1)使用增强for循环遍历
            System.out.println("使用增强for来遍历");
            for(Student student:students){
                System.out.println(student.toString());
            }
            //(2)使用迭代器遍历
            System.out.println("使用迭代器Iterator来遍历");
            Iterator<Student> it=students.iterator();
            while(it.hasNext()){
                Student s=it.next();
                System.out.println(s.toString());
            }
            System.out.println("====================================");
            //4.判断元素是否存在
            //也需要用到hasCode()、equals()方法,此处方法已被重写
            System.out.println(students.contains(s2));
            System.out.println(students.contains(new Student("ccc",15)));
            System.out.println(students.isEmpty());
            System.out.println("====================================");
    
        }
    /*结果:
    元素个数:4
    [name:ccc age:15, name:aaa age:5, name:ddd age:20, name:bbb age:10]
    ===================================
    元素个数:3
    [name:ccc age:15, name:ddd age:20, name:bbb age:10]
    ====================================
    使用增强for来遍历
    name:ccc age:15
    name:ddd age:20
    name:bbb age:10
    使用迭代器Iterator来遍历
    name:ccc age:15
    name:ddd age:20
    name:bbb age:10
    ====================================
    true
    true
    false
    ====================================
    */
    
    public class Student {
        //封装属性
        private int age;
        private String name;
        //构造器,new之后,程序先运行构造器再生成对象
        public Student(){
    
        }
        public Student(String name,int age) {
            super();
            this.age=age;
            this.name=name;
        }
    
        //可以通过快捷键Alt+Insert:重写常用的方法
        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 int hashCode() {
            int n1=this.name.hashCode();
            int n2=this.age;
            return n1+n2;
        }
    
        @Override
        public boolean equals(Object obj) {
    //        1.判断这两个对象是不是同一个引用
            if(this==obj){
                return true;
            }
    //        2.判断obj是否为null
            if(obj==null){
                return false;
            }
    //        3.判断两个对象是否为同一类型
            if(obj instanceof Student)//左边为对象,右边为类;
            //obj所指的实际类型是Student的子类型,则true
            {
    //            4.强制转换
                Student student=(Student) obj;
    //            5.
                if(this.name==student.name&&this.age==student.age)
                    return true;
            }
            return false;
        }
    
        @Override
        public String toString() {
            return "name:"+name+" "+"age:"+age;
        }
    }
    
  2. TreeSet类

    • 基于排列顺序实现元素不重复
    • 实现了SortedSet接口,对集合元素自动排序

    主要看CompareTo()是如何重写的

    • 元素对象的类型必须实现Comparable接口,指定排序规则
    • 通过CompareTo方法确定是否为重复元素
    • 存储结构:红黑树
//TreeSet的基本使用
public static void main(String[] args) {
//新建集合
        TreeSet<String> treeSet=new TreeSet<>();//后面<>的类型可以写也可以不写
//1.添加元素
        treeSet.add("aaa");
        treeSet.add("bbb");
        treeSet.add("ccc");
        treeSet.add("ddd");
        treeSet.add("abc");
        treeSet.add("bbb");//不能重复添加
        System.out.println("元素个数:" + treeSet.size());//集合长度(个数)
        System.out.println(treeSet.toString());//自动排序,有一定的规律但是没有下标
        System.out.println("====================================");
//2.删除元素
        treeSet.remove("ccc");//删除不能靠角标
        System.out.println("元素个数:" + treeSet.size());//集合长度(个数)
        System.out.println(treeSet.toString());//自动排序,有一定的规律但是没有下标
        System.out.println("====================================");
        //set1.clear()全部清除
// 3.遍历数据(只能使用增强for和迭代器)
        //1)增强for
        System.out.println("使用增强for来遍历");
        for (String s : treeSet) {
            System.out.println(s.toString());
        }
        //2)使用迭代器Iterator遍历,迭代器是个接口,方法如下
        //hasNext();判断有没有下一个元素
        //next();获取下一个元素
        //remove();删除当前元素
        System.out.println("使用迭代器Iterator来遍历");
        Iterator<String> it = treeSet.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s.toString());
        }
        System.out.println("====================================");

//4.判断
        System.out.println(treeSet.contains("000"));
        System.out.println(treeSet.isEmpty());
    }
/*结果:
元素个数:5
[aaa, abc, bbb, ccc, ddd]
====================================
元素个数:4
[aaa, abc, bbb, ddd]
====================================
使用增强for来遍历
aaa
abc
bbb
ddd
使用迭代器Iterator来遍历
aaa
abc
bbb
ddd
====================================
false
false
*/

注意:因为TreeSet集合的存储结构是红黑树,存放数据需要比较然后排序,然后才放入集合中,所以需要告诉其怎么进行排序。数据能放入集合、要实现必须要用到Comparable接口

所以:实现类---------->>>>public class Student implements Comparable{}

若compareTo()返回值为0--->则为重复,不能放入集合

//使用TreeSet集合保存数据
//存储结构:红黑树
//要求:元素必须要实现Comparable接口,重写的方法CompareTo()返回值为0,则为重复
    public static void main(String[] args) {
        //创建集合
       TreeSet<Student> students=new TreeSet<>();//引用自己创建的类,需要让他继承Comparable接口
        //继承了接口,需要重写接口的方法CompareTo(),制定比较规则
        //1.添加元素
        //在Student类中进行有参构造
        Student s1=new Student("aaa",5);
        Student s2=new Student("bbb",10);
        Student s3=new Student("ccc",15);
        Student s4=new Student("ccc",20);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s3);//重复,不会添加
        students.add(s4);
        students.add(new Student("ccc",20));//未重写CompareTo()方法前是可以添加,修改完添加不了
        System.out.println("元素个数:"+students.size());//集合长度(个数)
        System.out.println(students.toString());//此处的toString方法需要重写
        //TreeSet的排序方法是有一定顺序可言的,主要看CompareTo()是如何重写的
        System.out.println("===================================");
//2.删除元素
        //删除元素需要用到CompareTo()方法
        students.remove(new Student("aaa",5));
        System.out.println("元素个数:"+students.size());//集合长度(个数)
        System.out.println(students.toString());
        System.out.println("====================================");
//3.遍历元素
        //(1)使用增强for循环遍历
        System.out.println("使用增强for来遍历");
        for(Student student:students){
            System.out.println(student.toString());
        }
        //(2)使用迭代器遍历
        System.out.println("使用迭代器Iterator来遍历");
        Iterator<Student> it=students.iterator();
        while(it.hasNext()){
            Student s=it.next();
            System.out.println(s.toString());
        }
        System.out.println("====================================");
        //4.判断元素是否存在
        //也需要用到CompareTo()方法,此处方法已被重写
        System.out.println(students.contains(s2));
        System.out.println(students.contains(new Student("ccc",15)));
        System.out.println(students.isEmpty());
        System.out.println("====================================");
    }
/*
结果:
元素个数:4
[name:aaa age:5, name:bbb age:10, name:ccc age:15, name:ccc age:20]
===================================
元素个数:3
[name:bbb age:10, name:ccc age:15, name:ccc age:20]
====================================
使用增强for来遍历
name:bbb age:10
name:ccc age:15
name:ccc age:20
使用迭代器Iterator来遍历
name:bbb age:10
name:ccc age:15
name:ccc age:20
====================================
true
true
false
====================================
*/
public class Student implements Comparable<Student> {
    //封装属性
    private int age;
    private String name;
    //构造器,new之后,程序先运行构造器再生成对象
    public Student(){

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

    //可以通过快捷键Alt+Insert:重写常用的方法
    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 int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;
        return n1+n2;
    }

    @Override
    public boolean equals(Object obj) {
//        1.判断这两个对象是不是同一个引用
        if(this==obj){
            return true;
        }
//        2.判断obj是否为null
        if(obj==null){
            return false;
        }
//        3.判断两个对象是否为同一类型
        if(obj instanceof Student)//左边为对象,右边为类;
        //obj所指的实际类型是Student的子类型,则true
        {
//            4.强制转换
            Student student=(Student) obj;
//            5.
            if(this.name==student.name&&this.age==student.age)
                return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "name:"+name+" "+"age:"+age;
    }

    @Override
    public int compareTo(Student o) {
        //先比姓名
        int n1=this.name.compareTo(o.name);
        int n2=this.age-o.age;
        return n1==0?n2:n1;//如果n1比较的结果为0(名字相同),返回n2值,否则返回n1值
    }
}
  1. TreeSet集合补充

使用Comparator:实现定制比较器,来创建集合,并指定比较规则

//TreeSet集合的使用不使用Comparable接口
//使用Comparator:实现定制比较器(这是一个接口)
    public static void main(String[] args) {
        //创建集合,并制定比较规则------利用到匿名内部类
         TreeSet<Student> students=new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n1=o1.getAge()-o2.getAge();
                int n2=o1.getName().compareTo(o2.getName());
                return n1==0?n2:n1;//如果n1比较的结果为0(年龄相同),返回n2值(名字的值相减),否则返回n1值
            }
        });
        Student s1=new Student("aaa",5);
        Student s2=new Student("bbb",10);
        Student s3=new Student("ccc",15);
        Student s4=new Student("ccc",20);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s3);//重复,不会添加
        students.add(s4);
        students.add(new Student("ccc",20));
        //利用匿名内部类重写Comparator接口的compare()方法前是可以添加,修改完添加不了
        System.out.println("元素个数:"+students.size());//集合长度(个数)
        System.out.println(students.toString());//此处的toString方法需要重写


    }
/*结果:
元素个数:4
[name:aaa age:5, name:bbb age:10, name:ccc age:15, name:ccc age:20]
*/
  1. TreeSet集合的实例
    • 要求:使用TreeSet集合实现字符串按照长度进行排序
    • helloworld zhangsan lisi wangwu beijing guangzhou
//TreeSet集合的实例
//- 要求:使用TreeSet集合实现字符串按照长度进行排序
//- helloworld zhangsan lisi   beijing guangzhou
    public static void main(String[] args) {
 //利用Comparator接口实现定制比较
        //1.创建集合,比制定比较规则
        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;
            }
        });
        //2.添加数据
        treeSet.add("helloworld");
        treeSet.add("zhangsan");
        treeSet.add("lisi");
        treeSet.add("beijing");
        treeSet.add("guangzhou");
        System.out.println(treeSet.toString());
    }
/*结果:
[lisi, beijing, zhangsan, guangzhou, helloworld]
*/

六.Map接口与实现类

Map接口体系结构

1.Map父接口

  • 特点:存储一对数据(Key--Value)--->键值对

    无序无下标,键不能重复,值可以重复

    Map接口常用方法

//Map父接口
//方法的使用
    public static void main(String[] args) {
//创建Map集合(Map为接口,不能实例化)但是能创建对象;需要利用实现类
        Map<String,String> map=new HashMap<>();
//1.添加元素----->put()方法
          map.put("b","5");
          map.put("a","5");
          map.put("c","5");
          map.put("xyz","10");
          map.put("a","5");//不能添加相同的key和value
          map.put("a","10");//当key相同,value不同时,取代上一个key的value值
        //key不允许重复
        System.out.println("元素个数:"+map.size());
        System.out.println(map.toString());//无序的
        System.out.println("=============================");
//2.删除元素----->remove()方法
        //map.remove("xyz");
        map.remove("xyz","10");//两者都是将一对数据删除
        System.out.println("删除之后元素个数:"+map.size());
        System.out.println(map.toString());
        System.out.println("=============================");
//3.遍历元素
        //使用keySet()方法
        System.out.println("使用keySet()方法");
       Set<String> key= map.keySet();//keySet方法之后得到的是Set集合,得到key部分的集合数据
        for(String s:key){
            System.out.println(s+" "+map.get(s));//get()方法是得到该key的value值
        }
        //使用entrySet()方法
        System.out.println("使用entrySet()方法");
        Set<Map.Entry<String,String>> key_value =map.entrySet();
        //entrySet方法之后得到的是Set集合,得到key+value的一对集合数据,所以泛型的类型也是要一对
        for(Map.Entry<String,String> ss:key_value){
            System.out.println(ss.getKey()+" "+ss.getValue());
            //getkey()方法是得到key,getvalue()方法是得到value
        }
        System.out.println("=============================");
//4.查找元素
        System.out.println(map.containsKey("d"));// 查看是否有该key
        System.out.println(map.containsValue("5"));//查看是否有该value值
    }
/*结果:
元素个数:4
{a=10, b=5, c=5, xyz=10}
=============================
删除之后元素个数:3
{a=10, b=5, c=5}
=============================
使用keySet()方法
a 10
b 5
c 5
使用entrySet()方法
a 10
b 5
c 5
=============================
false
true
*/

2.Map集合的实现类

1)HashMap集合

  • !!HashSet其实就是用了HashMap的key!!

  • 存储结构:哈希表(数组+链表)

  • key值不能重复,value值可以重复

  • 可以用hashcode()和equals()方法的重写来确定key值(键)是否重复,重复则不加入集合

  public static void main(String Args[]){
        //1.创建集合
        HashMap<Student,String> hm1=new HashMap<>();
        //2.添加数据
        Student s1=new Student("aaa",5);
        Student s2=new Student("bbb",10);
        Student s3=new Student("ccc",15);
        Student s4=new Student("ddd",20);
        hm1.put(s1,"AAA");
        hm1.put(s2,"BBB");
        hm1.put(s3,"CCC");
        hm1.put(s4,"EEE");
        hm1.put(s4,"DDD");//Key值唯一,value值改变,取代上一个value值
        hm1.put(new Student("ddd",20),"DDD");//未修改hasdCode、equals方法前是可以添加,修改完添加不了

        System.out.println("元素个数:"+hm1.size());//集合长度(个数)
        System.out.println(hm1.toString());//此处的toString方法需要重写
        System.out.println("===================================");
        //3.删除数据
        hm1.remove(s4);
        //或者 hm1.remove(s4,"DDD");
        System.out.println("元素个数:"+hm1.size());//集合长度(个数)
        System.out.println(hm1.toString());//此处的toString方法需要重写
        System.out.println("===================================");
        //4.遍历数据
        //使用keySet()方法
        System.out.println("使用keySet()方法");
       // Set<Student> key = hm1.keySet();
        // keySet方法之后得到的是Set集合,得到key部分的集合数据
        for (Student s : hm1.keySet()) {
            System.out.println(s + " " + hm1.get(s));//get()方法是得到该key的value值
        }
        //使用entrySet()方法
        System.out.println("使用entrySet()方法");
        //Set<Map.Entry<Student, String>> key_value = hm1.entrySet();
        //entrySet方法之后得到的是Set集合,得到key+value的一对集合数据,所以泛型的类型也是要一对
        for (Map.Entry<Student, String> ss : hm1.entrySet()) {
            System.out.println(ss.getKey() + " " + ss.getValue());
            //getkey()方法是得到key,getvalue()方法是得到value
        }
        System.out.println("=============================");
//4.查找元素
        System.out.println(hm1.containsKey(s1));// 查看是否有该key
        System.out.println(hm1.containsValue("DDD"));//查看是否有该value值
    }
/*
结果:
元素个数:4
{name:ccc age:15=CCC, name:aaa age:5=AAA, name:ddd age:20=DDD, name:bbb age:10=BBB}
===================================
元素个数:3
{name:ccc age:15=CCC, name:aaa age:5=AAA, name:bbb age:10=BBB}
===================================
使用keySet()方法
name:ccc age:15 CCC
name:aaa age:5 AAA
name:bbb age:10 BBB
使用entrySet()方法
name:ccc age:15 CCC
name:aaa age:5 AAA
name:bbb age:10 BBB
=============================
true
false
*/
public class Student {
    //封装属性
    private int age;
    private String name;
    //构造器,new之后,程序先运行构造器再生成对象
    public Student(){

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

    //可以通过快捷键Alt+Insert:重写常用的方法
    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 int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;
        return n1+n2;
    }

    @Override
    public boolean equals(Object obj) {
//        1.判断这两个对象是不是同一个引用
        if(this==obj){ return true; }
//        2.判断obj是否为null
        if(obj==null){ return false; }
//        3.判断两个对象是否为同一类型
        if(obj instanceof Student)//左边为对象,右边为类;
        //obj所指的实际类型是Student的子类型,则true
        {//          4.强制转换
            Student student=(Student) obj;
//            5.
            if(this.name==student.name&&this.age==student.age)
                return true; }
        return false;
    }

    @Override
    public String toString() {
        return "name:"+name+" "+"age:"+age;
    }
}
  • HashMap源码分析

    • 刚创建HashMap之后没有添加元素 则table=null size=0;
    • 添加一个元素之后,HashMap的初始容量table就变为16
    • 当容量达到默认加载因子所要求的阈值(16*0.75)时,就扩容,每次为上一次的2倍

HashMap源码

备注:

①1左移4位=2^4=16:1<<4

②默认加载因子0.75f的意思是:当map集合内部元素超过75%就要扩容

2)TreeMap

  • !!TreeSet其实就是用了TreeMap的key!!

  • 实现了SortedMap接口(为Map的子接口)

  • 可以对key自动排序 主要看CompareTo()是如何重写的

  • 元素对象的类型必须实现Comparable接口,指定排序规则

  • 通过CompareTo方法确定是否为重复元素

  • 存储结构:红黑树

//存储结构:红黑树
//要求:元素必须要实现Comparable接口,重写的方法CompareTo()返回值为0,则为重复
    public static void main(String[] args) {
        TreeMap<Student,String> tm1=new TreeMap<>();//引用自己创建的类,需要让他继承Comparable接口
        //继承了接口,需要重写接口的方法CompareTo(),制定比较规则
        //2.添加数据
        Student s1=new Student("aaa",5);
        Student s2=new Student("bbb",10);
        Student s3=new Student("ccc",15);
        Student s4=new Student("ddd",20);
        tm1.put(s1,"AAA");
        tm1.put(s2,"BBB");
        tm1.put(s3,"CCC");
        tm1.put(s4,"EEE");
        tm1.put(s4,"DDD");//Key值唯一,value值改变,取代上一个value值
        tm1.put(new Student("ddd",20),"DDD");//未重写CompareTo()方法前是可以添加,修改完添加不了

        System.out.println("元素个数:"+tm1.size());//集合长度(个数)
        System.out.println(tm1.toString());//此处的toString方法需要重写
        //TreeSet的排序方法是有一定顺序可言的,主要看CompareTo()是如何重写的
        System.out.println("===================================");
        //3.删除数据
        //删除元素需要用到CompareTo()方法
        tm1.remove(new Student("ddd",20));
        //tm1.remove(s4);
        //或者 hm1.remove(s4,"DDD");
        System.out.println("元素个数:"+tm1.size());//集合长度(个数)
        System.out.println(tm1.toString());//此处的toString方法需要重写
        System.out.println("===================================");
        //4.遍历数据
        //使用keySet()方法
        System.out.println("使用keySet()方法");
        // Set<Student> key = hm1.keySet();
        // keySet方法之后得到的是Set集合,得到key部分的集合数据
        for (Student s : tm1.keySet()) {
            System.out.println(s + " " + tm1.get(s));//get()方法是得到该key的value值
        }
        //使用entrySet()方法
        System.out.println("使用entrySet()方法");
        //Set<Map.Entry<Student, String>> key_value = hm1.entrySet();
        //entrySet方法之后得到的是Set集合,得到key+value的一对集合数据,所以泛型的类型也是要一对
        for (Map.Entry<Student, String> ss : tm1.entrySet()) {
            System.out.println(ss.getKey() + " " + ss.getValue());
            //getkey()方法是得到key,getvalue()方法是得到value
        }
        System.out.println("=============================");
//4.查找元素
        //也需要用到CompareTo()方法,此处方法已被重写
        System.out.println(tm1.containsKey(s1));// 查看是否有该key
        System.out.println(tm1.containsKey(new Student("aaa",5)));
        System.out.println(tm1.containsKey(new Student("aaa",10)));
        System.out.println(tm1.containsValue("DDD"));//查看是否有该value值
    }
public class Student implements Comparable<Student> {
    //封装属性
    private int age;
    private String name;
    //构造器,new之后,程序先运行构造器再生成对象
    public Student(){

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

    //可以通过快捷键Alt+Insert:重写常用的方法
    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 int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;
        return n1+n2;
    }

    @Override
    public boolean equals(Object obj) {
//        1.判断这两个对象是不是同一个引用
        if(this==obj){ return true; }
//        2.判断obj是否为null
        if(obj==null){ return false; }
//        3.判断两个对象是否为同一类型
        if(obj instanceof Student)//左边为对象,右边为类;
        //obj所指的实际类型是Student的子类型,则true
        {//          4.强制转换
            Student student=(Student) obj;
//            5.
            if(this.name==student.name&&this.age==student.age)
                return true; }
        return false;
    }

    @Override
    public String toString() {
        return "name:"+name+" "+"age:"+age;
    }

    @Override
    public int compareTo(Student o) {
        //先比姓名
        int n1=this.name.compareTo(o.name);
        int n2=this.age-o.age;
        return n1==0?n2:n1;//如果n1比较的结果为0(名字相同),返回n2值,否则返回n1值
    }
}

posted @ 2021-02-01 20:25  维他命D片  阅读(42)  评论(0编辑  收藏  举报