> 文章列表 > 【算法与数据结构】2 梅开二度,线性查找的究极优化

【算法与数据结构】2 梅开二度,线性查找的究极优化

【算法与数据结构】2 梅开二度,线性查找的究极优化

请添加图片描述

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流

本文收录于算法与数据结构体系专栏,本专栏对于0基础者极为友好,欢迎与我一起完成算法与数据结构的从0到1的跨越

在这里插入图片描述

线性查找的究极优化

  • 1.前言
  • 2.泛型
    • 1.1粗略介绍泛型类
    • 1.2使用泛型方法
      • 1.2.1 mian()调用search()出错
      • 1.2.2 解析正确代码
  • 3 `==`or`equals`

1.前言

在上篇文章中,详细讲述了线性查找法并且对其进行了初步的优化:1️⃣使用static将方法写成一个静态的方法,2️⃣为了避免用户创造类的对象,将勾走凹函数声明为私有的。👉传送门:💖详解什么是算法?什么是线性查找法?💖

对于前面讲的线性查找法,它仍然存在一些需要改进的地方——当时的代码传入的是一个int型的数组,并且查找的元素也是一个int型,这些写完后,我们只可以在int型数组中查找一个int型的元素,但是在java中即使是基本类型也有8种,我们不可能对每一种类型都写一个线性查找的方法,这不是我们所希望的,不断重复写一个方法既不合理也是我们平时需要避免的

本篇文章就是为了学会我们应该如何避免重复写一个方法——泛型,这种语言机制就是为了可以应付不同的类型,一起来学习吧👇

2.泛型

1.1粗略介绍泛型类

  • 在Java语言中最常用的使用泛型方式就是定义一个泛型类——在类定义的后面加一个尖括号,里面写一个泛型的类型相应的代表的字母:<E>,在Java标准库中, 几乎所有的容器类都是泛型类
public class LinearSearch<E>{...}

1.2使用泛型方法

  • 对于上面的LinearSearch类,在具体使用的时候,并不是使用这个类的类对象,仅仅是使用这个类中相应的search()方法,所以我们将这个类定义成泛型类是没有意义的
  • 所以,我们实现的这个线性查找的算法类LinearSearch类不应该定义成泛型类,而是应该把search这个方法定义成是一个泛型方法——在public static后面加一个尖括号,里面写一个泛型的类型相应的代表的字母
//<E> 表示这个方法将会用到一个类型,类型E具体是什么,用户在调用的时候再指定
//data数组,是E这个类型的数组
//target,要查找的元素,也是E这个类型
public static <E> int search(E[] data, E target){...}

1.2.1 mian()调用search()出错

在这里插入图片描述

  • 原因: 在Java语言中,泛型只能接受类对象,而不能接受基本数据类型,图中的data数组是int类型,属于基本数据类型
  • 解决措施: Java语言对每一种基本数据类型都做了一个对应的 包装类,基本数据类型和所对应的包装类之间可以进行互相的转换
    在这里插入图片描述
  • 结论: 有了包装类的概念,当我们使用泛型的时候,如果我们想传入的类型是基本数据类型的话,只需要相应的把基本数据类型转化成对应的包装类

1.2.2 解析正确代码

  • 1️⃣search方法,已经是泛行方法了,对于泛行方法来说,接受的数据类型是E的data数组以及E类型的target,都不能是基本数据类型int,必须是类对象
  • 2️⃣只需要将data数组的类型修改为Integer类型
public class LinearSearchGeneric {private LinearSearchGeneric(){}public static <E> int search(E[] data, E target) {for (int i = 0; i < data.length; i++) {if (data[i] == target)return i;    //如果找到目标,返回对应的索引值}return -1;          //如果没有找到目标,返回-1}public static void main(String[] args) {//准备用于查找的数组 //👉int类型转化成对应的包装类IntegerInteger[] data = {24, 18, 12, 9, 16, 66, 32, 4};int res = LinearSearchGeneric.search(data, 16);System.out.println(res); //输出resint res2 = LinearSearchGeneric.search(data,666); //查找目标666System.out.println(res2);}
}
  • 3️⃣那为什么传入的target参数的值是16和666,并没有报错呢?
    • 在Java内部, 有一个 自动转换的机制 ,对于16而言,Java编译器知道这里应该是一个泛型类E target,对于泛型类应该是一个类对象,java语言就会自动把这个16这个基本数据类型给转换成它所对应的包装类
  • 4️⃣那为什么对于int型数组就会报错呢?
    • data是一个数组,java语言不能帮助我们自动把一个基本数据类型的数组转换成对应的包装类的数组
  • 对于老版本的Java的话,上面的main函数在调用search()的时候,应该写成LinearSearch.<Integer>search(data,16),在Java8中,<Integer>是可以省略的——我们不显示的告诉泛行方法的泛行的类型是什么
  • 在Java语言中,有一个叫做类型推断的机制——会根据传来的这个data是integer类型的数组以及16对应的包装类是integer类型,Java编译器可以自动的推断出用户调用的这个search所对应的这个泛型应该就是Integer这个类型

3 ==orequals

  • 上述代码中的if语句中判断使用的是data[i] == target,由于我们的data[i]此时已经不是一个基本数据类型,而是一个类对象,且target也是一个类对象
  • 判断两个类对象相等的时候,不应该用==, 因为 ==判断的是引用相等, 而我们在这里想判断的是值相等,应该调用equals方法
for(int i = 0; i < data.length; i ++)if(data[i].equals(target))return i;
  • ✌️那么现在,我们整个这个代码才是完全没有问题的

扩展:

  • 基于字符串进行处理的时候,对于字符串的判等使用了==可能会导致整个算法的逻辑错误
  • 在Java语言中,string字符串它是一个类,对于类对象之间的判断,一定要使用equals方法

在这里插入图片描述