Arrays、Lambda、方法引用、算法、正则表达式

124 阅读5分钟

Arrays、Lambda、方法引用、算法、正则表达式

1 Arrays

1.1 作用

​ 一个用于处理数组的工具类

1.2 常用方法

返回数组的内容: static String toString(数组)

从指定范围拷贝数组内容: static 数组 copyOfRange(数组, 开始索引, 结束索引) 注意: 包前不包后!

拷贝数组: static int[] copyOf(数组,int 长度)

把数组的内容改为新的数据: static void setAll(数组 , IntToDoubleFunction generator);

对数组的内容进行排序: 基本数据类型static void sort(数组), 自定义类型数组不支持直接排序, 需制定规则.

方法一:

 //让这个类实现Comparable接口,重写compareTo方法,自己来指定比较规则
public class Student implements Comparable<Student>{
    //省略创建类
}
 public int compareTo(Student o) {
        if(this.height > o.getHeight()){
            return 1;// 1 可以理解为换! positive
        }
        else if (this.height < o.getHeight()){
            return -1; // -1可以理解为不换 negative
        }else {
            if (this.age > o.getAge()){
                return -1;
            }else if (this.age < o.getAge()){
                return 1;
            }else {
                return 0;
            }
        }

第二种方法啊:


//在sort方法里面,创建Comparator接口,重写方法,指定比较规则
Arrays.sort(stu, new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        // if(o1.getAge() > o2.getAge()){
        //     return -1;
        // }else if(o1.getAge() < o2.getAge()){
        //     return 1;
        // }else{
        //     return 0;
        // }
        int i  = Double.compare(o1.getAge(),o2.getAge());
        // int i2 = Double.compare(o1.getHeight(),o2.getAge());
        return i;
    }
});

二分查找元素: static int binarySearch(数组, 元素)

2 Lambda 表达式

2.1 作用

​ 简化匿名内部类的格式。这个匿名内部类的接口一定要是一个函数式接口 (里面有且只有一个抽象方法)

2.2 格式
	(重写方法的参数)->{
                   方法体;
               }
2.3 方法引用
	不在乎实现的过程, 只在乎实现的结果!
2.3.1 静态方法引用

​ 1) 格式: 类名::静态方法

​ 2) 使用场景: 如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用。

​ 3) 代码: A a2 = MyUtils::getMax;

public interface findMax {
    int findMax(int a, int b);
}
public interface findMin {
    int findMin(int a, int b);
}
public class MyUtils {

    // 静态方法,用于获取两个整数的最大值
    public static int getMax(int a, int b) {
        return a > b ? a : b;
    }

    // 实例方法,获取两个数字的最小值
    public int getMin(int a, int b) {
        return a < b ? a : b;
    }
}
public class test {
    public static void main(String[] args) {
        int a = 14;
        int b = 28;

        // 之前学过的 (匿名内部类)
        findMax max1 = new findMax() {
            @Override
            public int findMax(int a, int b) {
                int c = MyUtils.getMax(a, b );
                return c;
            }
        };
        System.out.println(max1.findMax(a,b));

        // Lampda
        findMax max2 = (int a1, int b1)->{
            int c = MyUtils.getMax(a, b );
            return c;
        };

        findMax max3 = MyUtils::getMax;
        System.out.println(max3.findMax(a,b));
2.3.2 实例方法的引用

​ 1) 格式: 对象名::实例方法

​ 2) 使用场景: 如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用。

​ 3) 代码: B b3 = mu::getMin; //写的也是方法的名字就可以了

​ B b4 = new MyUtils()::getMin; //写的也是方法的名字就可以了

2.3.3 特定类型方法的引用

​ 1) 格式: 类型::方法

​ 2) 使用场景: 如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调, 后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用

​ 3) 代码:

 String[] names = new String[]{"baby", "Angela", "about", "eson", "Jack", "jack2", "rose"};

Arrays.sort(names, String::compareToIgnoreCase);
2.3.4 构造器引用

​ 1) 格式: 类名::new

​ 2) 使用场景: 如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用。

​ 3) 代码: C c3 = Student::new;

3 算法

3.1 冒泡排序
3.1.1 核心思想

​ 每次从数组中找出最大值放在数组的后面去。

3.1.2 实现步骤

​ 1) 确定总共需要做几轮: 数组的长度-1.

​ 2) 每轮比较几次

​ 3) 当前位置大于后一个位置则交换数据

3.1.3 代码实现
public static void main(String[] args) {
        int[] arr = {5, 2, 3, 1};
        //外部循环控制执行的次数
        /*
             第一轮    i = 0    2 3 1 5
             第二轮    i = 1    2 1 3 5
             第三轮    i = 2    1 2 3 5
         */
        for (int i = 0; i < arr.length - 1; i++) {
            //内部循环实现获取较大值【两两比较】
            for (int j = 0; j < arr.length - i - 1; j++) {
                //相邻的两个进行比较 , 如果当前元素值 大于下一个元素的值,则进行位置的交换
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
                System.out.println(Arrays.toString(arr));
            }
        }
    }
3.2 选择排序
3.2.1 核心思想

​ 每轮选择当前位置,开始找出后面的较小值与该位置交换

3.2.2 实现步骤

​ 1) 确定总共需要做几轮: 数组的长度-1.

​ 2) 控制每轮从以前位置为基准,与后面元素选择几次。

​ 3) 当前位置大于后一个位置则交换数据

3.2.3 代码实现
  public static void main(String[] args) {
        int[] arr = {5, 1, 3, 2};
        //定义外部循环,代表循环执行的次数
        for (int i = 0; i < arr.length - 1; i++) {
            System.out.println("第" + (i + 1) + "轮");
            //定义内部循环,代表选择的次数
            for (int j = i + 1; j < arr.length; j++) {
                //用当前的位置的元素和后面的元素进行判断,如果当前位置后面位置的元素大,则交换位置
                if (arr[i] > arr[j]) {
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
                //可以查看这个程序交换的流程
                System.out.println(Arrays.toString(arr));
            }
        }
        System.out.println(Arrays.toString(arr));
    }
3.3 二分查找
3.3.1 前提条件

​ 数组中的数据必须是有序的

3.3.2 核心思想

​ 每次排除一半的数据,查询数据的性能明显提高极多!

3.3.3 实现步骤

​ 1) 定义变量记录左边和右边位置。

​ 2) 使用while循环控制二分查询(条件是左边位置<=右边位置)

​ 3) 循环内部获取中间元素索引

​ 4) 判断当前要找的元素如果大于中间元素,左边位置=中间索引+1

​ 5) 判断当前要找的元素如果小于中间元素,右边位置=中间索引-1

​ 6) 判断当前要找的元素如果等于中间元素,返回当前中间元素索引。

3.3.4 代码实现
public static int myBinarySearch(int[] arr, int num) {
        //我们首先应该要有两个索引,代表 左边的索引, 以及 右边的索引
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            //开始去找中间的索引  =  (左边索引 + 右边的索引) / 2
            int mid = (left + right) / 2;
            //我们用中间索引的元素和 num 进行比较
            if (arr[mid] == num) {
                // 如果中间元素 和 num 值相等,直接返回索引。代表找到
                return mid;
            } else if (arr[mid] > num) {
                // 中间的元素 > num 大, 改变右边的索引 = 中间索引 - 1
                right = mid - 1;
            } else if (arr[mid] < num) {
                // 中间的元素 < num 小,  改变左边的索引 = 中间索引 + 1
                left = mid + 1;
            }
        }
        //返回一个负数 代表找不到
        return -1;

    }

4 正则表达式

4.1 概念

​ 用来校验数据格式是否合法

4.2 作用

​ 1) 用来校验数据格式是否合法

​ 2) 在一段文本中查找满足要求的内容

4.3 正则规则
4.3.1 字符类【匹配一个字符】

​ [abc] : 只能是a, b, 或c

​ [ ^abc] : 除了a, b, c之外的任何字符

​ [a-zA-Z] : a到z A到Z,包括(范围)

​ [a-d[m-p]] : a到d,或m到p

​ [a-z&&[def]] : d, e, 或f(交集)

​ [a-z&& [ ^bc]] : a到z,除了b和c(等同于[ad-z])

​ [a-z&&[ ^m-p]] : a到z,除了m到p(等同于[a-lq-z]

4.3.2 预定义字符(只匹配单个字符)

​ . 任何字符

​ \d 一个数字: [0-9]

​ \D 非数字: [ ^0-9]

​ \s 一个空白字符:

​ \S 非空白字符: [ ^\s]

​ \w [a-zA-Z_0-9]

​ \W [ ^\w] 一个非单词字符

4.3.3 数量词

​ X? X , 一次或0次

​ X* X,零次或多次

​ X+ X , 一次或多次

​ X {n} X,正好n次

​ X {n, } X,至少n次

​ X {n,m} X,至少n但不超过m次

4.3.4 分割/爬取数据

import java.util.Arrays;

public class Demo04 {
    public static void main(String[] args) {
        String str = "张三asdasdasdasd18dasdasdadasd广州市";
        // 把所有的按照分段方式,替换为一个 ","  ==>  张三,18,广州
        String result = str.replaceAll("[a-z]{1,}", ",");
        System.out.println(result);

        // 把上面的字符串中个人信息分割出来
        String[] ss = str.split("[a-z]{1,}");
        System.out.println(Arrays.toString(ss)); // [张三, 18, 广州市]
    
    }

}
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Demo03 {
    /*
        信息爬取

     */
    public static void main(String[] args) {
        String data = "来黑马程序员学习Java," +
                "电话:18512516758,18512508907" +
                "或者联系邮箱:boniu@itcast.com.cn" +
                "座机电话:01036517895,010-98951256" +
                "邮箱:bozai@itcast.cn," +
                "邮箱2:dlei0009@163.com," +
                "热线电话:400-618-9090 ,400-618-4000," +
                "4006184000,4006189090";
        //请把下面文本中的电话,邮箱,座机号码,热线都爬取出来。
        String regex = "(1[3-9]\\d{9})|(0\\d{2}-?[1-9]\\d{7})|(400-\\d{3}-\\d{4})|(400\\d{3}\\d{4})|([a-zA-Z0-9]{1,}@[a-zA-Z0-9]{2,8}(\\.[a-z]{2,3}){1,2})";

        // 我们先要创建一个Pattern对象,用来封装正则
        Pattern pattern = Pattern.compile(regex);
        // 指定爬取的数据
        Matcher matcher = pattern.matcher(data);
        // 拿数据  ==> 1.先判断有没有数据  2.再去拿数据
        while (matcher.find()){
            String s = matcher.group();
            System.out.println(s);
        }


    }
}