《数据结构与算法分析Java》引论

本文深入探讨了Java泛型的概念及其实现原理,包括协变、逆变的应用,以及如何正确使用泛型方法和集合。此外,还介绍了函数对象的概念及其在实际编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引论

数学公式回顾

几何级数公式
在这里插入图片描述

算术级数、调和级数

在这里插入图片描述

模运算

在这里插入图片描述

最常用的两种证明方法

  • 归纳法
  • 反证法

递归的四大法则

  • 基准情形(边界条件)
  • 不断逼近基准情形
  • 设计法则(所有的递归调用能运行)
  • 合成效益法则(不要在不同的递归调用中做重复的工作)

循环不定:边界条件无法到达或者没有边界条件。用词典的例子来说就是查不到或循环解释。

在pre-Java5中实现泛型构件

泛型机制

在实现功能的过程中,除去对象的类型外,实现的方法是相同的,就用泛型实现来描述这种基本的功能。原先实现的思路主要是Object类、包装类、接口三种

协变、逆变和不变

在这里插入图片描述

Java5泛型构件

根本意义在于使用Java泛型后类型兼容出问题时抛出的是编译时异常而非运行时异常。

这里以协变数组类型举例

class Person{
}
class Student extends Person{
}
class Employee extends Person{
}
public class Main {
    public static void main(String[] args) {
        Person[] persons = new Employee[5]; //编译 arrays are compatible
        persons[0] = new Student(); //编译 Student IS-A Person
    }
}

//Exception in thread "main" java.lang.ArrayStoreException: Student
//	at Main.main(Main.java:17)

这里 persons[0] 引用的是Employee,而Student IS-NOT-A Employee,Person数组其实并不允许内容多种多样,arr[0] 引用的是,但也不能抛出 ClassCastException ,这里并不存在类型转换。最终抛出的是 java.lang.ArrayStoreException。

协变的一致性:原子类型协变能推出结构类型协变。换言之,参数为People 的方法能够接受Student 实参能推出——peoples 参数接受Students形参。

  • 数组协变的一致性:Employee IS-A Person可以推出 Employee[] IS-A Person[]

  • 泛型集合与泛型的协变则不能一致,泛型集合则不是协变的,这样类型不兼容就会报编译时错误

// 泛型参数自身的协变
ArrayList<Person> people0 = new ArrayList<>();
people0.add(new Student());

//泛型集合是非协变
ArrayList<Student> people = new ArrayList<>();
test(people);
//Required type:
//Collection
//<Person>
//Provided:
//ArrayList
//<Student>

泛型:类型限界

// 注意泛型方法的说明应当在方法修饰符之后,返回类型声明之前

// 这里万一缺少对T实现Comparable接口的说明是肯定不行滴
public static <T> void findMax0(List<T> tC) {
    T t = tC.get(0);
    for (T i :
            tC) {
        t = (t.compareTo(i)) > 0 ? t : i;
    }
}
// 这里说明泛型实现接口注意是用extends哦
    // 这里问题在于没有去限制T实现的compareTo的参数,这个参数正好是Comparable接口的泛型对象
    public static <T extends Comparable> T findMax1(List<T> tC) {
        T t = tC.get(0);
        for (T i :
                tC) {
            t = (t.compareTo(i)) > 0 ? t : i;
        }
        return t;
    }
    // 这样做太过直接粗暴了,只能比自己啊
    // let me see see, 还会有啥好比的捏
    // 巧啊,如果Comparable是在T的父类这实现的呢
    // 这样怎么比. 只能比爹类了不是,我们原来限制比较的类型可没说限制到连自个不能比啊,我们是说要限制到比的是有用的,自己要比,爹类也要比,哪个爹呢,所有爹是不是应该都可以去比一比?对头
    public static <T extends Comparable<T>> T findMax2(List<T> tC) {
        T t = tC.get(0);
        for (T i :
                tC) {
            t = (t.compareTo(i)) > 0 ? t : i;
        }
        return t;
    }

完美版本

class Shape implements Comparable<Shape> {
    int EdgeCount;

    public Shape(int edgeCount) {
        EdgeCount = edgeCount;
    }

    public int compareTo(Shape s) {
        System.out.println(s.getClass().getName());
        return Integer.compare(this.EdgeCount, s.EdgeCount);
    }
}

class Square extends Shape{
    public Square(int edgeCount) {
        super(edgeCount);
    }
}

public class Main {
    //非常妙,这里?自然是Shape, 也就是说限制到本身或父类实现过就行
    public static <T extends Comparable<? super T>> T findMax3(List<T> tC) {
            T t = tC.get(0);
            for (T i :
                    tC) {
                t = (t.compareTo(i)) > 0 ? t : i;
            }
            return t;
        }

    public static void main(String[] args) {
        ArrayList<Square> squares = new ArrayList<>();
        squares.add(new Square(2));
        squares.add(new Square(4));
        squares.add(new Square(1));
        squares.add(new Square(3));
        System.out.println(findMax3(squares).EdgeCount);
    }
}

类型擦除

泛型类可以由编译器通过所谓类型擦除过程变为非泛型类,自动地生成原始类。类型变量由它们的类型界限来替代,一般来说由Object 替换,限制了extends 就用最靠近的父类来替换。

函数对象

一个函数通过将其放在一个对象内部进行传递(直接传对象),这样的对象叫函数对象。

class Shape {
    int EdgeCount;

    public Shape(int edgeCount) {
        this.EdgeCount = edgeCount;
    }
}

public class Main {
    // 对Shape进行比较但可能不知道比什么,直接传接口实现类的对象即可
    public static <T> T findMax3(T[] arr, Comparator<? super T> comparator) {
        T t = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (comparator.compare(t, arr[i]) < 0){
                t = arr[i];
            }
        }
        return t;
    }

    public static void main(String[] args) {
        Shape[] shapes = new Shape[]{
                new Shape(3),
                new Shape(2),
                new Shape(4)
        };
        System.out.println(
            findMax3(shapes,
                     new Comparator<Shape>() {
                         @Override
                         public int compare(Shape o1, Shape o2){
                             return Integer.compare(
                                 o1.EdgeCount * o1.EdgeCount,
                                 o2.EdgeCount * o2.EdgeCount
                             );
                         }
                     }
                    ).EdgeCount
        );
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值