java进阶八(泛型,set,红黑树)

JavaSE进阶第八天

课程大纲:

  • 泛型
  • Set集合
    • TreeSet
    • HashSet
  • 数据结构-二叉树

一.泛型

1.什么是泛型

 广泛的类型,类似于小数数学中的x变量,你想让它是什么类型就可以是什么类型
 泛型是JDK5之后出现的新特性(自动拆装箱、增强for和泛型),
 泛型是一种在编译时期的一种安全机制,泛型只在编译时期有效,编译之后没有了(泛型的擦除)

2.泛型的好处

  • 把运行时期的问题提前到了编译时期
  • 避免了强制类型转换

3.泛型可以使用的地方

image-20210912162210719

4.如何使用泛型

 泛型一般定义在<>中,要起一个名称(变量名),名称可以是一个字母组成,也可以是多个字母,
 一个泛型可以是一部分组成,也可以多多部分组成。泛型在传递的时候,只能传递引用类型
            <E>
            <T>
            <K>
            <V>
            <HELLO>
            <AB>
            <K,V>
            <X,Y,Z,...>

5.泛型的格式

5.1泛型类

  public class 类名<E> { 
  }

E泛型变量,在类中肯定就会使用到,可以用在方法上(返回值类型、参数类型、方法体中变量类型)
或者成员变量上,当做类型来使用。

什么时候确定泛型具体类型:创建对象的时候确定泛型具体类型
//就是一个泛型类
public class Box<E> {
    private E Element;


    public E getElement() {
        return Element;
    }

    public void setElement(E element) {
        Element = element;
    }
}
Box<String> box = new Box<>();
box.setElement("给小丽的土味情话!");
System.out.println(box.getElement());

Box<Integer> inter = new Box<>();
inter.setElement(11);
System.out.println(inter.getElement());

image-20210912163045193

5.2泛型方法

修饰符 <T> 返回值类型 方法名(参数列表) {
	}


T泛型变量,在方法中肯定会使用到,可以用在当前泛型方法上(返回值类型、参数类型、方法体中变量类型),出了该方法无法使用。
    
 什么时候确定泛型具体类型:调用的时候确定泛型具体类型
   ArrayList<String> list = new ArrayList<>();
        list.add("给小丽的土味情话");
        list.add("给小路的土味情话");
        list.add("给小花的土味情话");
//      将list集合转成一个数组并返回
//       如果是空参的,那么返回的数组类型为Object类型的
        Object[] objects = list.toArray();
        System.out.println(Arrays.toString(objects) +"-----"+"Object类型");
        System.out.println("-------------------------");
//        将list集合转成一个数组并返回
//        list.toArray(T[] a)
        String[] strings = list.toArray(new String[list.size()]);
        System.out.println(Arrays.toString(strings)+"-----"+"String类型");

image-20210912164925115

public static void main(String[] args) {
    ArrayList<String> list = addElement(new ArrayList<String>(), "a", "b", "c", "d");
    System.out.println(list+"-------"+"String类型");
    System.out.println("------------------------");
    ArrayList<Integer> inter = addElement(new ArrayList<Integer>(), 1, 2, 3, 4);
    System.out.println(inter+"-------"+"Integer类型");
}
public  static <T>  ArrayList<T>  addElement(ArrayList<T> list,T t1,T t2,T t3,T t4){
    list.add(t1);
    list.add(t2);
    list.add(t3);
    list.add(t4);
    return list;

}

image-20210912165301997

5.3泛型接口

public interface 接口名<E> {
	}


E泛型变量,在接口中肯定就会使用到,可以用在方法上(返回值类型、参数类型)或者常量上,当做类型来使用。
    
 什么时候确定泛型具体类型:
    1、创建实现类对象的时候确定泛型具体类型
    2、定义实现类的时候确定泛型具体类型
    3、定义子接口的时候确定泛型具体类型
    
interface Genericity<E>{
    public abstract void method(E e);
}
class GenericityImpl1<E> implements  Genericity<E>{

    @Override
    public void method(E e) {
        System.out.println(e);
    }
}
 GenericityImpl1<String> genericity = new GenericityImpl1<>();
        genericity.method("小丽给我的土味情话");

image-20210912170108795

方式二
class GenericityImpl2 implements  Genericity<Integer>{

    @Override
    public void method(Integer integer) {
        System.out.println(integer);
    }
}


class GenericityImpl3 implements  Genericity<String>{


    @Override
    public void method(String string) {
        System.out.println(string);
    }
}
GenericityImpl2 genericityImpl2 = new GenericityImpl2();
genericityImpl2.method(12);

System.out.println("--------------");
GenericityImpl3 objectGenericityImpl3 = new GenericityImpl3();
objectGenericityImpl3.method("给安迪的土味情话");

image-20210912170350754

5.4类型通配符

  • 类型通配符:<?>
  • ArrayList<?> :表示元素类型未知的ArrayList,它的元素可以匹配任何的类型
  • 但是并不能把元素添加到ArrayList中,获取出来的也是父类类型
类型通配符上限:<? extends 类型>
    ArrayList<? extends Number>:它表示的类型是Number或者其子类型

类型通配符下限:<? super 类型>
    ArrayList<? super Number>:它表示的类型是Number或者其父类型

  ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        ArrayList<Number> list3 = new ArrayList<>();
        ArrayList<Object> list4 = new ArrayList<>();
        printList(list1);
        printList(list2);
  public static void printList(ArrayList<?> list) {	//可以传任意泛型
      
    }
//    表示传递进来集合的类型,可以是Number类型,也可以是Number所有的子类类型
    public static void method1(ArrayList<? extends Number> list) {

    }

//    表示传递进来集合的类型,可以是Number类型,也可以是Number所有的父类类型
    public static void method2(ArrayList<? super Number> list) {}
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
ArrayList<Number> list3 = new ArrayList<>();
ArrayList<Object> list4 = new ArrayList<>();

 		 method1(list1);  //number的子类
         method1(list3);    //numberz自己
//       method1(list4);  // 报错 Object类型比Number要大
//       method2(list1);  报错,Integer类型比Number小
         method2(list4);   //number的父类
         method2(list3);   //number自己

5.5Collection中涉及泛型通配符的方法

	boolean addAll(Collection<? extends E> c):将b集合中的所有元素添加到a集合中
    boolean containsAll(Collection<?> c):判断a集合中是否包含b集合中所有的元素
    boolean removeAll(Collection<?> c):删除a集合中包含b集合的元素(删除交集)
    boolean retainAll(Collection<?> c):保留a集合中包含b集合的元素(保留交集)
        
    要操作这些方法必须有两个集合,一个是调用者集合,一个是参数集合
    a.addAll(b),a就是调用者集合,b就是参数集合

二.Set集合

1.Set集合的特点

  • 不能存储重复
  • 没有索引,不能使用普通for循环遍历,也不能通过索引来获取,删除集合里面的元素
  • 不能保证存取有序
  Set<String> set = new TreeSet<>();
        set.add("ccc");
        set.add("aaa");
        set.add("aaa");
        set.add("bbb");

只能用增强for或迭代器遍历

  Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }

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

        for (String s : set) {
            System.out.println(s);
        }

image-20210913130429023

2.TreeSet

2.1TreeSet集合特点

  • 不包含重复元素的集合
  • 没有带索引的方法
  • 可以将元素按规律进行排序

2.2 自然排序

2.2.1实现方式:
  • 将元素所在的类实现Comparable接口
  • 在类中重写抽象方法compareTo方法( compareTo方法中的代码就是用于设置规则的)
2.2.2 compareTo方法
两个对象:
    this和o
    都是当前类的对象

this:代表当前要添加的元素
   o:集合中已经存储的元素

this在前,o在后是升序
o在前,this在后是降序
       
       
返回值
    正数:元素放在后边(右边/下面)
    0:删除
    负数:元素放在前边(左边/上面)
TreeSet<Student> ts = new TreeSet<>();
Student s1 = new Student("dahei",80,80,80);
Student s2 = new Student("erhei",90,90,90);
Student s4 = new Student("erhei2",95,85,90);
Student s3 = new Student("xiaohei",100,100,100);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);

for (Student t : ts) {
    System.out.println(t);
}
public class Student implements Comparable<Student>{}
 public int compareTo(Student o) {
        int result = o.getScore() - this.getScore();
        result = result == 0 ? o.getChinese() - this.getChinese() : result;
        result = result == 0 ? o.getMath() - this.getMath() : result;
        result = result == 0 ? o.getEnglish() - this.getEnglish() : result;
        result = result == 0 ? o.getName().compareTo(this.getName()) : result;
        return result;
    }

image-20210913131618276

2.3 比较器排序

2.3.1实现方式
  • 定义一个类实现Comparator接口
  • 在实现类中重写抽象方法compare方法(compare方法中的代码就是用于设置规则的)
  • 在创建TreeSet对象的时候,将实现类对象传递到TreeSet的构造方法中
2.3.2 compare方法
两个对象:
 o1和o2
    表示元素对象

    o1:代表当前要添加的元素
    o2:集合中已经存储的元素

    o1在前,o2在后是升序
    o2在前,o1在后是降序
       
       
返回值
    正数:元素放在后边(右边/下面)
    0:删除
    负数:元素放在前边(左边/上面)
        
        
   注:o1相当于自然排序中的this
      o2相当于自然排序中的o
 TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
            @Override
            public int compare(Teacher o1, Teacher o2) {
                //o1表示现在要存入的那个元素
//                o2表示已经存入到集合中的元素
                int result = o1.getAge() - o2.getAge();
                result = result == 0 ? o1.getName().compareTo(o2.getName()) : result;
                return result;
            }
        });
        Teacher t1 = new Teacher("zhangsan", 23);
        Teacher t2 = new Teacher("lisi", 22);
        Teacher t3 = new Teacher("wangwu", 24);
        Teacher t4 = new Teacher("zhaoliu", 24);
        ts.add(t1);
        ts.add(t2);
        ts.add(t3);
        System.out.println(ts);

image-20210913132358786

2.4两种排序方式的选择

  • 自定义类: 两种方式任选一种,都能达到一样的目的,一般选择自然方式比较多
  • JDK提供的类: 比如Integer、String等,里面有默认的自然方式排序,当默认的方式不满足条件的时候选择比较器排序
  • 当两种排序方式同时存在的时候,比较器排序方法会覆盖自然排序方法

三.二叉树

3.1结构

3.1.1节点的结构

image-20210914183633499

3.1.2二叉树的结构

image-20210914183736443

  • 高度(层数) :4
  • 最顶层的节点:根节点
  • 4是7的左节点,10是7的右节点

3.1.3二叉查找树

image-20210914184044236

特点: 1.每一个节点上最多有两个子节点
     2.每一个节点的左子节点都是小于自己的
     3.每一个节点的右子节点都是大于自己的

3.2二叉查找树添节点

规则:
    小的存左边
    大的存右边
    一样的不存

image-20210914184859507

3.3平衡二叉树

  • 二叉树左右两个子树的高度差不超过1
  • 任意节点的左右两个子树都是一颗平衡二叉树

image-20210914190041964

image-20210914190106532

3.4二叉查找树

image-20210914190406083

条件:利用左旋和右旋机制保证树的平衡

注意点:

  • 判断添加元素与当前节点的关系
  • 成功添加之后,判断是否破坏了二叉树的平衡

3.5左旋

image-20210914190754892

  • 逆时针旋转
  • 右子节点变成父节点(根节点)
  • 原先的根节点降级变成左子节点
  • 将多余的左子节点出让,给降级的节点作为右子节点

image-20210914191026740

3.6右旋

image-20210914191051516

  • 顺时针旋转
  • 左子节点变成父节点(根节点)
  • 原先的根节点降级变成右子节点
  • 将多余的右子节点出让,给降级的节点作为左子节点

image-20210914191225805

3.7旋转的四种情况

3.7.1左左

当根节点左子树的左左子树节点插入,导致二叉树不平衡

image-20210914193045300

image-20210914193151341

3.7.2左右

当根节点左子树的右子树节点插入,导致二叉树不平衡

image-20210914193250991

image-20210914193319725

image-20210914193355157

image-20210914193431264

3.7.3右右

当根节点右子树的右子树有节点插入,导致二叉树不平衡

image-20210914193627102

image-20210914193650478

image-20210914193732156

3.7.4右左

当根节点右子树的左子树有节点插入,导致二叉树不平衡

image-20210914193834162

image-20210914193930485

image-20210914193955524
h9J-1631619754621)]

[外链图片转存中…(img-WxvYmz0z-1631619754621)]

3.7.2左右

当根节点左子树的右子树节点插入,导致二叉树不平衡

[外链图片转存中…(img-g8CAtXxu-1631619754622)]

[外链图片转存中…(img-FCDZyupa-1631619754622)]

[外链图片转存中…(img-UbdzvBbV-1631619754623)]

[外链图片转存中…(img-kNJg1gsz-1631619754623)]

3.7.3右右

当根节点右子树的右子树有节点插入,导致二叉树不平衡

[外链图片转存中…(img-JiEO64nj-1631619754623)]

[外链图片转存中…(img-fgkzj9ak-1631619754624)]

[外链图片转存中…(img-4HiWodV2-1631619754624)]

3.7.4右左

当根节点右子树的左子树有节点插入,导致二叉树不平衡

[外链图片转存中…(img-l6LCd7az-1631619754625)]

[外链图片转存中…(img-UznRa7Vh-1631619754625)]

[外链图片转存中…(img-amp6FGBC-1631619754626)]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值