泛型类、泛型方法、泛型接口

泛型深入

泛型概述

例如:

(源代码)

[GenericsDemo1]

package com.itheima.a04mygenerics;


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

public class GenericsDemo1 {
    public static void main(String[] args) {
        //没有泛型的时候,集合如何存储数据
        //结论:
        //如果我们没有给集合指定类型,默认认为所有的数据类型都是Object类型
        //此时可以往集合添加任意的数据类型。
        //带来一个坏处:我们在获取数据的时候,无法使用他的特有行为。

        //此时推出了泛型,可以在添加数据的时候就把类型进行统一。
        //而且我们在获取数据的时候,也省的强转了,非常的方便。

        //1.创建集合的对象
        ArrayList list = new ArrayList();

        //2.添加数据
        list.add(123);
        list.add("aaa");
        list.add(new Student("zhangsan",123));


        //3.遍历集合获取里面的每一个元素
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            //str.length();
            System.out.println(obj);//123 aaa Student{name = zhangsan, age = 123}
        }


    }
}

[Student]

package com.itheima.a04mygenerics;

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


    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

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

(运行结果截图)

泛型的好处

泛型的细节

泛型可以在很多地方进行定义

泛型类

例如:

(源代码)

[MyArrayList<E>]

package com.itheima.a04mygenerics;


import java.util.Arrays;

/*
*       当我在编写一个类的时候,如果不确定类型,那么这个类就可以定义为泛型类。
* */
public class MyArrayList<E> {

    Object[] obj = new Object[10];
    int size;

    /*
    E : 表示是不确定的类型。该类型在类名后面已经定义过了。
    e:形参的名字,变量名
    * */
    public boolean add(E e){
        obj[size] = e;
        size++;
        return true;
    }


    public E get(int index){
        return (E)obj[index];
    }


    @Override
    public String toString() {
        return Arrays.toString(obj);
    }
}

[GenericsDemo2]

package com.itheima.a04mygenerics;

public class GenericsDemo2 {
    public static void main(String[] args) {
       MyArrayList<String> list = new MyArrayList<>();

        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        System.out.println(list.get(0));//aaa

        System.out.println(list);//[aaa, bbb, ccc, null, null, null, null, null, null, null]

        System.out.println("--------------------");


        MyArrayList<Integer> list2 = new MyArrayList<>();
        list2.add(123);
        list2.add(456);
        list2.add(789);


        int i = list2.get(0);
        System.out.println(i);//123


        System.out.println(list2);//[123, 456, 789, null, null, null, null, null, null, null]
    }
}

(运行结果截图)

泛型方法

格式:

练习:泛型方法的练习

(源代码)

[ListUtil]

package com.itheima.a04mygenerics;

import java.util.ArrayList;

public class ListUtil {
    private ListUtil(){}

    //类中定义一个静态方法addAll,用来添加多个集合的元素。
    
    /*
    *   参数一:集合
    *   参数二~最后:要添加的元素
    *
    * 
    */
    
    public static<E> void addAll(ArrayList<E> list, E e1,E e2,E e3,E e4){
        list.add(e1);
        list.add(e2);
        list.add(e3);
        list.add(e4);
    }

    
    public static<E> void addAll2(ArrayList<E> list, E...e){
        for (E element : e) {
            list.add(element);
        }
    }
    

    public void show(){
        System.out.println("尼古拉斯·纯情·天真·暖男·阿玮");
    }
    
}

[GenericsDemo3]

package com.itheima.a04mygenerics;


import java.util.ArrayList;

/*
    定义一个工具类:ListUtil
    类中定义一个静态方法addAll,用来添加多个集合的元素。
*/
public class GenericsDemo3 {
    public static void main(String[] args) {

        ArrayList<String> list1 = new ArrayList<>();
        ListUtil.addAll(list1, "aaa", "bbb", "ccc", "ddd");
        System.out.println(list1);//[aaa, bbb, ccc, ddd]


        ArrayList<Integer> list2 = new ArrayList<>();
        ListUtil.addAll2(list2,1,2,3,4);
        System.out.println(list2);//[1, 2, 3, 4]

    }
}

(运行结果截图)

泛型接口

方式1:实现类给出具体的类型

例如:

(源代码)

package com.itheima.a04mygenerics;

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

public class MyArrayList2 implements List<String> {
    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator<String> iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }

    @Override
    public boolean add(String s) {
        return false;
    }

    @Override
    public boolean remove(Object o) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends String> c) {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends String> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public String get(int index) {
        return null;
    }

    @Override
    public String set(int index, String element) {
        return null;
    }

    @Override
    public void add(int index, String element) {

    }

    @Override
    public String remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }

    @Override
    public ListIterator<String> listIterator() {
        return null;
    }

    @Override
    public ListIterator<String> listIterator(int index) {
        return null;
    }

    @Override
    public List<String> subList(int fromIndex, int toIndex) {
        return null;
    }
}

package com.itheima.a04mygenerics;

public class GenericsDemo4 {
    public static void main(String[] args) {
        /*
            泛型接口的两种使用方式:
                1.实现类给出具体的类型
                2.实现类延续泛型,创建实现类对象时再确定类型
        */


        MyArrayList2 list = new MyArrayList2();
        list.add("abc");
        




    }
}

方式2:实现类延续泛型,创建对象时再确定

例如:

(源代码)

package com.itheima.a04mygenerics;

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

public class MyArrayList3<E> implements List<E> {
    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator<E> iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }

    @Override
    public boolean add(E e) {
        return false;
    }

    @Override
    public boolean remove(Object o) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public E get(int index) {
        return null;
    }

    @Override
    public E set(int index, E element) {
        return null;
    }

    @Override
    public void add(int index, E element) {

    }

    @Override
    public E remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }

    @Override
    public ListIterator<E> listIterator() {
        return null;
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return null;
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return null;
    }
}

package com.itheima.a04mygenerics;

public class GenericsDemo4 {
    public static void main(String[] args) {
        /*
            泛型接口的两种使用方式:
                1.实现类给出具体的类型
                2.实现类延续泛型,创建实现类对象时再确定类型
        */


        MyArrayList3<String> list = new MyArrayList3<>();
        


    }
}

泛型的通配符和综合练习

泛型的继承和通配符

例如:

(源代码)

package com.itheima.a04mygenerics;


import java.util.ArrayList;

public class GenericsDemo5 {
    public static void main(String[] args) {
        /*
            泛型不具备继承性,但是数据具备继承性
        */

        //创建集合的对象
        ArrayList<Ye> list1 = new ArrayList<>();
        ArrayList<Fu> list2 = new ArrayList<>();
        ArrayList<Zi> list3 = new ArrayList<>();

        //调用method方法
        //泛型不具备继承性
        //method(list1);
        //method(list2);
        //method(list3);


        //但是数据具备继承性
        list1.add(new Ye());
        list1.add(new Fu());
        list1.add(new Zi());


    }


    /*
    * 此时,泛型里面写的是什么类型,那么只能传递什么类型的数据。
    * */
    public static void method(ArrayList<Ye> list) {

    }


}


练习

需求:定义一个方法,形参是一个集合,但是集合中的数据类型不确定

(源代码)

package com.itheima.a04mygenerics;

import java.util.ArrayList;

public class GenericsDemo6 {
    public static void main(String[] args) {
        /*
        *   需求:
        *       定义一个方法,形参是一个集合,但是集合中的数据类型不确定。
        *
        * */


        //创建集合的对象
        ArrayList<Ye> list1 = new ArrayList<>();
        ArrayList<Fu> list2 = new ArrayList<>();
        ArrayList<Zi> list3 = new ArrayList<>();

        ArrayList<Student2> list4 = new ArrayList<>();

        method(list1);
        method(list2);
        //method(list3);


        //method(list4);


    }

    /*
     * 此时,泛型里面写的是什么类型,那么只能传递什么类型的数据。
     * 弊端:
     *      利用泛型方法有一个小弊端,此时他可以接受任意的数据类型
     *      Ye  Fu   Zi    Student
     *
     * 希望:本方法虽然不确定类型,但是以后我希望只能传递Ye Fu Zi
     *
     * 此时我们就可以使用泛型的通配符:
     *      ?也表示不确定的类型
     *      他可以进行类型的限定
     *      ? extends E: 表示可以传递E或者E所有的子类类型
     *      ? super E:表示可以传递E或者E所有的父类类型
     *
     * 应用场景:
     *      1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
     *      2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符
     * 泛型的通配符:
     *      关键点:可以限定类型的范围。
     *
     * */
    public static void method(ArrayList<? super Fu> list) {

    }
}

class Ye {
}

class Fu extends Ye {
}

class Zi extends Fu {
}

class Student2{}

案例

需求:

(源代码)

[Animal]

package com.itheima.a05test;

public abstract class Animal {
    private String name;
    private int age;


    public Animal() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }


    public abstract void eat();

    public String toString() {
        return "Animal{name = " + name + ", age = " + age + "}";
    }
}

[Cat]

package com.itheima.a05test;

public abstract class Cat extends Animal{

    //1.继承抽象类,重写里面所有的抽象方法
    //2.本身Cat也是一个抽象的,让Cat的子类再重写重写方法

    //此时采取第二种处理方案
    //因为猫的两个子类中eat的方法体还是不一样的。

}

[PersianCat]

package com.itheima.a05test;

public class PersianCat extends Cat {
    @Override
    public void eat() {
        System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的波斯猫,正在吃小饼干");
    }
}

[LiHua]

package com.itheima.a05test;

public class LiHuaCat extends Cat {
    @Override
    public void eat() {
        System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的狸花猫,正在吃鱼");
    }
}

[Dog]

package com.itheima.a05test;

public abstract class Dog extends Animal{
    //1.继承抽象类,重写里面所有的抽象方法
    //2.本身Dog也是一个抽象的,让Dog的子类再重写重写方法

    //此时采取第二种处理方案
    //因为猫的两个子类中eat的方法体还是不一样的。
}

[TeddyDog]

package com.itheima.a05test;

public class TeddyDog extends Dog{
    @Override
    public void eat() {
        System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的泰迪,正在吃骨头,边吃边蹭");
    }
}

[HuskyDog]

package com.itheima.a05test;

public class HuskyDog extends Dog {
    @Override
    public void eat() {
        System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的哈士奇,正在吃骨头,边吃边拆家");
    }
}

[Test1]

package com.itheima.a05test;

import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) {
        /*
            需求:
                定义一个继承结构:
                                    动物
                         |                           |
                         猫                          狗
                      |      |                    |      |
                   波斯猫   狸花猫                泰迪   哈士奇


                 属性:名字,年龄
                 行为:吃东西
                       波斯猫方法体打印:一只叫做XXX的,X岁的波斯猫,正在吃小饼干
                       狸花猫方法体打印:一只叫做XXX的,X岁的狸花猫,正在吃鱼
                       泰迪方法体打印:一只叫做XXX的,X岁的泰迪,正在吃骨头,边吃边蹭
                       哈士奇方法体打印:一只叫做XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家

            测试类中定义一个方法用于饲养动物
                public static void keepPet(ArrayList<???> list){
                    //遍历集合,调用动物的eat方法
                }
            要求1:该方法能养所有品种的猫,但是不能养狗
            要求2:该方法能养所有品种的狗,但是不能养猫
            要求3:该方法能养所有的动物,但是不能传递其他类型
         */


        ArrayList<PersianCat> list1 = new ArrayList<>();
        ArrayList<LiHuaCat> list2 = new ArrayList<>();
        ArrayList<TeddyDog> list3 = new ArrayList<>();
        ArrayList<HuskyDog> list4 = new ArrayList<>();

        keepPet(list1);
        keepPet(list2);
        keepPet(list3);
        keepPet(list4);
    }

    //该方法能养所有的动物,但是不能传递其他类型
    public static void keepPet(ArrayList<? extends Animal> list){
        //遍历集合,调用动物的eat方法
    }



  /*  //  要求2:该方法能养所有品种的狗,但是不能养猫
    public static void keepPet(ArrayList<? extends Dog> list){
        //遍历集合,调用动物的eat方法
    }*/


    /*//要求1:该方法能养所有品种的猫,但是不能养狗
    public static void keepPet(ArrayList<? extends Cat> list){
        //遍历集合,调用动物的eat方法
    }*/
}

总结

数据结构

数据结构(二叉树、二叉查找树、平衡二叉树)

         

数据结构(树)

数据结构(二叉查找树)

添加节点

(二叉树)的遍历方式

前序遍历

中序遍历

后序遍历

层序遍历

数据结构(平衡二叉树)

数据结构(树的演变)

数据结构(平衡二叉树查找机制)

数据结构(平衡二叉树)左旋

数据结构(平衡二叉树)右旋

数据结构(平衡二叉树)需要旋转的四种情况

数据结构(平衡二叉树)左左

数据结构(平衡二叉树)左右

数据结构(平衡二叉树)右右

数据结构(平衡二叉树)右左

数据结构(平衡二叉树)小结

数据结构(红黑树、红黑规则、添加节点处理方案详解)

数据结构(红黑树)

数据结构(红黑树)红黑规则

数据结构(红黑树)添加节点规则

HashSet、LinkedHashSet、TreeSet

Set

Set系列集合

Set集合的实现类

Set接口中的方法基本上与Collection的API一致

练习:存储字符串并遍历

(源代码)

package com.itheima.a05myset;


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

public class A01_SetDemo1 {
    public static void main(String[] args) {
       /*
           利用Set系列的集合,添加字符串,并使用多种方式遍历。
            迭代器
            增强for
            Lambda表达式

        */


        //1.创建一个Set集合的对象
        Set<String> s = new HashSet<>();

        //2,添加元素
        //如果当前元素是第一次添加,那么可以添加成功,返回true
        //如果当前元素是第二次添加,那么添加失败,返回false
        s.add("张三");
        s.add("张三");
        s.add("李四");
        s.add("王五");

        //3.打印集合
        //无序
        //System.out.println(s);//[李四, 张三, 王五]

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

        //增强for
       /* for (String str : s) {
            System.out.println(str);
        }*/

        // Lambda表达式
        s.forEach( str->System.out.println(str));


    }
}

(运行结果截图)

总结

HashSet

HashSet底层原理

哈希表组成

哈希值

对象的哈希值特点

例如:
(源代码)

[Student]

package com.itheima.a05myset;

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

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

    @Override
    public boolean equals(Object o) {
        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);
    }
}

[A02_HashSetDemo1]

package com.itheima.a05myset;

public class A02_HashSetDemo1 {
    public static void main(String[] args) {
        /*
            哈希值:
                对象的整数表现形式
                1. 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
                2. 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
                3. 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)

         */

        //1.创建对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("zhangsan",23);

        //2.如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
        //  如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
        System.out.println(s1.hashCode());//-1461067292
        System.out.println(s2.hashCode());//-1461067292


        //在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。
        //哈希碰撞
        System.out.println("abc".hashCode());//96354
        System.out.println("acD".hashCode());//96354

    }
}
(运行结果截图)

HashSetJDK8以前底层原理

HashSetJDK8以后底层原理

HashSet的三个问题

案例:利用HashSet集合去除重复元素

(源代码)

[Student]

package com.itheima.a05myset;

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

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

    @Override
    public boolean equals(Object o) {
        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);
    }
}

[A03_HashSetDemo2]

package com.itheima.a05myset;

import java.util.HashSet;

public class A03_HashSetDemo2 {
    public static void main(String[] args) {
        /* 需求:创建一个存储学生对象的集合,存储多个学生对象。
            使用程序实现在控制台遍历该集合。
            要求:学生对象的成员变量值相同,我们就认为是同一个对象


        String   Integer
*/
        //1.创建三个学生对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("wangwu",25);
        Student s4 = new Student("zhangsan",23);


        //2.创建集合用来添加学生
        HashSet<Student> hs = new HashSet<>();

        //3.添加元素
        System.out.println(hs.add(s1));//true
        System.out.println(hs.add(s2));//true
        System.out.println(hs.add(s3));//true
        System.out.println(hs.add(s4));//false

        //4.打印集合
        System.out.println(hs);//[Student{name = wangwu, age = 25}, Student{name = lisi, age = 24}, Student{name = zhangsan, age = 23}]




    }
}
(运行结果截图)

LinkedHashSet

LinkedHashSet底层原理

例如:

(源代码)

[Student]

package com.itheima.a05myset;

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

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

    @Override
    public boolean equals(Object o) {
        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);
    }
}

[A04_LinkedHashSetDemo]

package com.itheima.a05myset;

import java.util.LinkedHashSet;

public class A04_LinkedHashSetDemo {
    public static void main(String[] args) {
        //1.创建4个学生对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("wangwu",25);
        Student s4 = new Student("zhangsan",23);


        //2.创建集合的对象
        LinkedHashSet<Student> lhs = new LinkedHashSet<>();


        //3.添加元素
        System.out.println(lhs.add(s3));//true
        System.out.println(lhs.add(s2));//true
        System.out.println(lhs.add(s1));//true
        System.out.println(lhs.add(s4));//false

        //4.打印集合
        System.out.println(lhs);//[Student{name = wangwu, age = 25}, Student{name = lisi, age = 24}, Student{name = zhangsan, age = 23}]
    }
}

(运行结果截图)

总结

TreeSet

TreeSet特点

练习:TreeSet对象排序练习

(源代码)
package com.itheima.a05myset;


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

public class A04_TreeSetDemo1 {
    public static void main(String[] args) {
        /*
        *
        *       需求:利用TreeSet存储整数并进行排序
        *
        * */


        //1.创建TreeSet集合对象
        TreeSet<Integer> ts = new TreeSet<>();

        //2.添加元素
        ts.add(4);
        ts.add(5);
        ts.add(1);
        ts.add(3);
        ts.add(2);

        //3.打印集合
        //System.out.println(ts);

        //4.遍历集合(三种遍历)
        //迭代器
        Iterator<Integer> it = ts.iterator();
        while(it.hasNext()){
            int i = it.next();
            System.out.println(i);
        }
        System.out.println("--------------------------");

        //增强for
        for (int t : ts) {
            System.out.println(t);
        }
        System.out.println("--------------------------");

        //lambda
        ts.forEach( i-> System.out.println(i));

    }
}
(运行结果截图)

TreeSet集合默认的规则

TreeSet两种比较方法

【第一种排序方法】

练习:TreeSet对象排序练习题

(分析)

(源代码)

[Student]

package com.itheima.a05myset;

public class Student implements Comparable<Student>{
    private String name;
    private int age;


    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

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

    @Override
    //this:表示当前要添加的元素
    //o:表示已经在红黑树存在的元素

    //返回值:
    //负数:表示当前要添加的元素是小的,存左边
    //正数:表示当前要添加的元素是大的,存右边
    //0 :表示当前要添加的元素已经存在,舍弃
    public int compareTo(Student o) {
        System.out.println("--------------");
        System.out.println("this:" + this);
        System.out.println("o:" + o);
        //指定排序的规则
        //只看年龄,我想要按照年龄的升序进行排列
        return this.getAge() - o.getAge();
    }
}

[A05_TreeSetDemo2]

package com.itheima.a05myset;


import java.util.TreeSet;

public class A05_TreeSetDemo2 {
    public static void main(String[] args) {
        /*
            需求:创建TreeSet集合,并添加3个学生对象
            学生对象属性:
                姓名,年龄。
                要求按照学生的年龄进行排序
                同年龄按照姓名字母排列(暂不考虑中文)
                同姓名,同年龄认为是同一个人

            方式一:
                默认的排序规则/自然排序
                Student实现Comparable接口,重写里面的抽象方法,再指定比较规则
        */


        //1.创建三个学生对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("wangwu",25);
        Student s4 = new Student("zhaoliu",26);


        //2.创建集合对象
        TreeSet<Student> ts = new TreeSet<>();

        //3.添加元素
        ts.add(s3);
        ts.add(s2);
        ts.add(s1);
        ts.add(s4);

        //4.打印集合
        System.out.println(ts);//[Student{name = zhangsan, age = 23}, Student{name = lisi, age = 24}, Student{name = wangwu, age = 25}, Student{name = zhaoliu, age = 26}]


        //HashCode和equals方法 : 哈希表有关的
        //TreeSet 底层是红黑树

    }
}

(运行结果截图)

【第二种排序方式】

(源代码)

package com.itheima.a05myset;

import java.util.TreeSet;

public class A06_TreeSetDemo3 {
    public static void main(String[] args) {
       /*
            需求:请自行选择比较器排序和自然排序两种方式;
            要求:存入四个字符串, “c”, “ab”, “df”, “qwer”
            按照长度排序,如果一样长则按照首字母排序

            采取第二种排序方式:比较器排序
        */

        //1.创建集合
        //o1:表示当前要添加的元素
        //o2:表示已经在红黑树存在的元素
        //返回值规则跟之前是一样的
        TreeSet<String> ts = new TreeSet<>((o1, o2)->{
                // 按照长度排序
                int i = o1.length() - o2.length();
                //如果一样长则按照首字母排序
                i = i == 0 ? o1.compareTo(o2) : i;
                return i;
        });

        //2.添加元素
        ts.add("c");
        ts.add("ab");
        ts.add("df");
        ts.add("qwer");


        //3.打印集合
        System.out.println(ts);


    }
}

(运行结果截图)

练习:TreeSet对象排序练习题

(源代码)

[Student2]

package com.itheima.a05myset;

public class Student2 implements Comparable<Student2> {
    //姓名
    private String name;
    //年龄
    private int age;
    //语文成绩
    private int chinese;
    //数学成绩
    private int math;
    //英语成绩
    private int english;


    public Student2() {
    }

    public Student2(String name, int age, int chinese, int math, int english) {
        this.name = name;
        this.age = age;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return chinese
     */
    public int getChinese() {
        return chinese;
    }

    /**
     * 设置
     * @param chinese
     */
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    /**
     * 获取
     * @return math
     */
    public int getMath() {
        return math;
    }

    /**
     * 设置
     * @param math
     */
    public void setMath(int math) {
        this.math = math;
    }

    /**
     * 获取
     * @return english
     */
    public int getEnglish() {
        return english;
    }

    /**
     * 设置
     * @param english
     */
    public void setEnglish(int english) {
        this.english = english;
    }

    public String toString() {
        return "Student2{name = " + name + ", age = " + age + ", chinese = " + chinese + ", math = " + math + ", english = " + english + "}";
    }

   /* 按照总分从高到低输出到控制台
    如果总分一样,按照语文成绩排
    如果语文一样,按照数学成绩排
    如果数学成绩一样,按照英语成绩排
    如果英文成绩一样,按照年龄排
    如果年龄一样,按照姓名的字母顺序排
    如果都一样,认为是同一个学生,不存。*/
    @Override
    public int compareTo(Student2 o) {
        int sum1 = this.getChinese() + this.getMath() + this.getEnglish();
        int sum2 = o.getChinese() + o.getMath() + o.getEnglish();

        //比较两者的总分
        int i = sum1 - sum2;
        //如果总分一样,就按照语文成绩排序
        i = i == 0 ? this.getChinese() - o.getChinese() : i;
        //如果语文成绩一样,就按照数学成绩排序
        i = i == 0 ? this.getMath() - o.getMath() : i;
        //如果数学成绩一样,按照英语成绩排序(可以省略不写)
        i = i == 0 ? this.getEnglish() - o.getEnglish() : i;
        //如果英文成绩一样,按照年龄排序
        i = i == 0 ? this.getAge() - o.getAge() : i;
        //如果年龄一样,按照姓名的字母顺序排序
        i = i == 0 ? this.getName().compareTo(o.getName()) : i;
        return i;
    }
}

[A07_TreeSetDemo4]

package com.itheima.a05myset;

import java.util.TreeSet;

public class A07_TreeSetDemo4 {
    public static void main(String[] args) {
      /*  需求:创建5个学生对象
        属性:(姓名,年龄,语文成绩,数学成绩,英语成绩),
        按照总分从高到低输出到控制台
        如果总分一样,按照语文成绩排
        如果语文一样,按照数学成绩排
        如果数学成绩一样,按照英语成绩排
        如果英文成绩一样,按照年龄排
        如果年龄一样,按照姓名的字母顺序排
        如果都一样,认为是同一个学生,不存。

        第一种:默认排序/自然排序
        第二种:比较器排序

        默认情况下,用第一种排序方式,如果第一种不能满足当前的需求,采取第二种方式。


        课堂练习:
            要求:在遍历集合的时候,我想看到总分。

      */


        //1.创建学生对象
        Student2 s1 = new Student2("zhangsan",23,90,99,50);
        Student2 s2 = new Student2("lisi",24,90,98,50);
        Student2 s3 = new Student2("wangwu",25,95,100,30);
        Student2 s4 = new Student2("zhaoliu",26,60,99,70);
        Student2 s5 = new Student2("qianqi",26,70,80,70);


        //2.创建集合
        TreeSet<Student2> ts = new TreeSet<>();

        //3.添加元素
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        //4.打印集合
        //System.out.println(ts);
        for (Student2 t : ts) {
            System.out.println(t);
        }

    }
}
(运行结果截图)

总结

使用场景

更多推荐