【Java学习笔记】常用API、Lambda、 常见算法

前言

  • 该文章为Java自学笔记案例:面向对象进阶
  • 学习视频为https://www.bilibili.com/video/av250694651

目录

  • 前言
  • 日期与时间
    • Date
    • SimpleDateFormat
    • Calendar
  • JDK8新增日期类
    • 概述、LocalTime /LocalDate / LocalDateTime
    • Instant
    • DateTimeFormatter
    • Duration/Period
    • ChronoUnit
  • 包装类
  • 正则表达式
    • 正则表达式概述、初体验
    • 正则表达式的匹配规则
    • 正则表达式的常见案例
    • 正则表达式在方法中的应用
    • 正则表达式爬取信息
  • Arrays类
    • Arrays类概述,常用功能演示
    • Arrays类对于Comparator比较器的支持
  • 常见算法
    • 冒泡排序
    • 选择排序
    • 二分查找
  • Lambda表达式
    • Lambda概述
    • Lambda实战-简化常见函数式接口
    • Lambda表达式的省略规则

日期与时间

Date

Date 类概述:Date类代表当前所在系统的日期时间信息。
Date的构造器

名称 说明
public Date() 创建一个Date对象,代表的是系统当前此刻日期时间。

Data的常用方法

名称 说明
public long getTime() 返回从1970年1月1日 00:00:00走到此刻的总的毫秒数

时间毫秒值 -> 日期对象

构造器 说明
public Date(long time) 把时间毫秒值转换成Date日期对象。
Data方法 说明
public void setTime(long time) 设置日期对象的时间为当前时间毫秒值对应的时间

案例:

public class DateDemo1 {
    public static void main(String[] args) {
        // 1、创建一个Date类的对象:代表系统此刻日期时间对象
        Date d = new Date();
        System.out.println(d);

        // 2、获取时间毫秒值
        long time = d.getTime();
        System.out.println(time);

        System.out.println("----------------------------");
        // 1、得到当前时间
        Date d1 = new Date();
        System.out.println(d1);

        // 2、当前时间往后走 1小时  121s
        long time2 = System.currentTimeMillis();
        time2 += (60 * 60 + 121) * 1000;

        // 3、把时间毫秒值转换成对应的日期对象。
        Date d2 = new Date(time2);
        System.out.println(d2);

        Date d3 = new Date();
        d3.setTime(time2);
        System.out.println(d3);

    }
}

SimpleDateFormat

SimpleDateFormat 类作用:可以去完成日期时间的格式化操作。
在这里插入图片描述
构造器

构造器 说明
public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat,使用指定的格式

格式化方法

格式化方法 说明
public final String format(Date date) 将日期格式化成日期/时间字符串
public final String format(Object time) 将时间毫秒值式化成日期/时间字符串

格式化的时间形式的常用的模式对应关系如下:
【Java学习笔记】常用API、Lambda、 常见算法_第1张图片

SimpleDateFormat解析字符串时间成为日期对象

解析字符串时间成为日期对象:
2011-11-11 11:11:22 -> Date日期对象

解析方法 说明
public Date parse(String source) 从给定字符串的开始解析文本以生成日期

案例:

public class SimpleDateFormatDemo01 {
    public static void main(String[] args) {
        // 1、日期对象
        Date d = new Date();
        System.out.println(d);

        // 2、格式化这个日期对象 (指定最终格式化的形式)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
        // 3、开始格式化日期对象成为喜欢的字符串形式
        String rs = sdf.format(d);
        System.out.println(rs);

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

        // 4、格式化时间毫秒值
        // 需求:请问121秒后的时间是多少
        long time1 = System.currentTimeMillis() + 121 * 1000;
        String rs2 = sdf.format(time1);
        System.out.println(rs2);
    }
}

public class SimpleDateFormatDemo2 {
    public static void main(String[] args) throws ParseException {
        // 目标: 学会使用SimpleDateFormat解析字符串时间成为日期对象。
        // 有一个时间 2021年08月06日 11:11:11 往后 2天 14小时 49分 06秒后的时间是多少。
        // 1、把字符串时间拿到程序中来
        String dateStr = "2021年08月06日 11:11:11";

        // 2、把字符串时间解析成日期对象(本节的重点):形式必须与被解析时间的形式完全一样,否则运行时解析报错!
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date d = sdf.parse(dateStr);

        // 3、往后走2天 14小时 49分 06秒
        long time = d.getTime() + (2L*24*60*60 + 14*60*60 + 49*60 + 6) * 1000;

        // 4、格式化这个时间毫秒值就是结果
        System.out.println(sdf.format(time));
    }
}

秒杀活动:
需求:

  • 某购物网站举办秒杀活动,开始时间和结束时间如左图所示,当前活动结束后,系统记录到2位用户的付款时间分别如下:
    • 小贾下单并付款的时间为:2020年11月11日 0:03:47
    • 小皮下单并付款的时间为:2020年11月11日 0:10:11
  • 规则:顾客的付款时间必须在秒杀时间之内,请判断出两位顾客是否秒杀成功
public class SimpleDateFormatTest3 {
    public static void main(String[] args) throws ParseException {
        // 1、开始 和 结束时间
        String startTime = "2021-11-11 00:00:00";
        String endTime = "2021-11-11 00:10:00";

        // 2、小贾 小皮
        String xiaoJia =  "2021-11-11 00:03:47";
        String xiaoPi =  "2021-11-11 00:10:11";

        // 3、解析他们的时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d1 = sdf.parse(startTime);
        Date d2 = sdf.parse(endTime);
        Date d3 = sdf.parse(xiaoJia);
        Date d4 = sdf.parse(xiaoPi);

        if(d3.after(d1) && d3.before(d2)){
            System.out.println("小贾秒杀成功,可以发货了!");
        }else {
            System.out.println("小贾秒杀失败!");
        }

        if(d4.after(d1) && d4.before(d2)){
            System.out.println("小皮秒杀成功,可以发货了!");
        }else {
            System.out.println("小皮秒杀失败!");
        }
    }
}

Calendar

Calendar概述

  • Calendar代表了系统此刻日期对应的日历对象。
  • Calendar是一个抽象类,不能直接创建对象。

Calendar日历类创建日历对象的方法:

方法名 说明
public static Calendar getInstance() 获取当前日历对象

Calendar常用方法:

方法名 说明
public int get(int field) 取日期中的某个字段信息。
public void set(int field,int value) 修改日历的某个字段信息。
public void add(int field,int amount) 为某个字段增加/减少指定的值
public final Date getTime() 拿到此刻日期对象。
public long getTimeInMillis() 拿到此刻时间毫秒值

注意:calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化。

案例:

public class CalendarDemo{
    public static void main(String[] args) {
        // 1、拿到系统此刻日历对象
        Calendar cal = Calendar.getInstance();
        System.out.println(cal);

        // 2、获取日历的信息:public int get(int field):取日期中的某个字段信息。
        int year = cal.get(Calendar.YEAR);
        System.out.println(year);

        int mm = cal.get(Calendar.MONTH) + 1;
        System.out.println(mm);

        int days = cal.get(Calendar.DAY_OF_YEAR) ;
        System.out.println(days);

        // 3、public void set(int field,int value):修改日历的某个字段信息。
        // cal.set(Calendar.HOUR , 12);
        // System.out.println(cal);

        // 4.public void add(int field,int amount):为某个字段增加/减少指定的值
        // 64天后是什么时间
        cal.add(Calendar.DAY_OF_YEAR , 64);
        cal.add(Calendar.MINUTE , 59);

        //  5.public final Date getTime(): 拿到此刻日期对象。
        Date d = cal.getTime();
        System.out.println(d);

        //  6.public long getTimeInMillis(): 拿到此刻时间毫秒值
        long time = cal.getTimeInMillis();
        System.out.println(time);
    }
}

JDK8新增日期类

概述、LocalTime /LocalDate / LocalDateTime

概述:

  • 从Java 8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:

LocalDate:不包含具体时间的日期。
LocalTime:不含日期的时间。
LocalDateTime:包含了日期及时间。
Instant:代表的是时间戳。
DateTimeFormatter 用于做时间的格式化和解析的
Duration:用于计算两个“时间”间隔
Period:用于计算两个“日期”间隔

  • 新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便。
  • 其次,新API的类型几乎全部是不变类型(和String的使用类似),可以放心使用不必担心被修改。

LocalDate、LocalTime、LocalDateTime

  • 他们分别表示日期,时间,日期时间对象,他们的类的实例是不可变的对象。
  • 他们三者构建对象和API都是通用的

构建对象的方式如下:

方法名 说明
public static Xxxx now(); 静态方法,根据当前时间创建对象
public static Xxxx of(…); 静态方法,指定日期/时间创建对象

样例
LocaDate localDate = LocalDate.now();
LocalTime llocalTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
LocalDate localDate1 = LocalDate.of(2099 , 11,11);
LocalTime localTime1 = LocalTime.of(11, 11, 11);
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);

LocalDate、LocalTime、LocalDateTime获取信息的API

方法名 说明
public int geYear() 获取年
public int getMonthValue() 获取月份(1-12)
Public int getDayOfMonth() 获取月中第几天乘法
Public int getDayOfYear() 获取年中第几天
Public DayOfWeek getDayOfWeek() 获取星期

LocalDateTime的转换API

方法名 说明
public LocalDate toLocalDate() 转换成一个LocalDate对象
public LocalTime toLocalTime() 转换成一个LocalTime对象

修改相关的API

  • LocalDateTime 综合了 LocalDate 和 LocalTime 里面的方法,所以下面只用 LocalDate 和 LocalTime 来举例。
  • 这些方法返回的是一个新的实例引用,因为LocalDateTime 、LocalDate 、LocalTime 都是不可变的。
方法名 说明
plusDays, plusWeeks, plusMonths, plusYears 向当前 LocalDate 对象添加几天、 几周、几个月、几年
minusDays, minusWeeks, minusMonths, minusYears 从当前 LocalDate 对象减去几天、 几周、几个月、几年
withDayOfMonth, withDayOfYear, withMonth, withYear 将月份天数、年份天数、月份、年份修改为指定的值并返回新的LocalDate对象
isBefore, isAfter 比较两个 LocalDate

Instant

Instant时间戳:JDK8获取时间戳特别简单,且功能更丰富。Instant类由一个静态的工厂方法now()可以返回当前时间戳。
时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是类似JDK8 以前的Date。
Instant和Date这两个类可以进行转换。

public class Demo05Instant {
    public static void main(String[] args) {
        // 1、得到一个Instant时间戳对象
        Instant instant = Instant.now();
        System.out.println(instant);

        // 2、系统此刻的时间戳怎么办?
        Instant instant1 = Instant.now();
        System.out.println(instant1.atZone(ZoneId.systemDefault()));

        // 3、如何去返回Date对象
        Date date = Date.from(instant);
        System.out.println(date);

        Instant i2 = date.toInstant();
        System.out.println(i2);
    }
}

DateTimeFormatter

在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。
正反都能调用format方法。

public class Demo06DateTimeFormat {
    public static void main(String[] args) {
        // 本地此刻  日期时间 对象
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);

        // 解析/格式化器
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
        // 正向格式化
        System.out.println(dtf.format(ldt));
        // 逆向格式化
        System.out.println(ldt.format(dtf));

        // 解析字符串时间
        DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 解析当前字符串时间成为本地日期时间对象
        LocalDateTime ldt1 = LocalDateTime.parse("2019-11-11 11:11:11" ,  dtf1);
        System.out.println(ldt1);
        System.out.println(ldt1.getDayOfYear());
    }
}

Duration/Period

Period:

  • 在Java8中,我们可以使用以下类来计算日期间隔差异:java.time.Period
  • 主要是 Period 类方法 getYears(),getMonths() 和 getDays() 来计算,只能精确到年月日。
  • 用于 LocalDate 之间的比较。
public class Demo07Period {
    public static void main(String[] args) {
        // 当前本地 年月日
        LocalDate today = LocalDate.now();
        System.out.println(today);//

        // 生日的 年月日
        LocalDate birthDate = LocalDate.of(1998, 10, 13);
        System.out.println(birthDate);

        Period period = Period.between(birthDate, today);//第二个参数减第一个参数

        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
    }
}

Duration:

  • 在Java8中,我们可以使用以下类来计算时间间隔差异:java.time.Duration
  • 提供了使用基于时间的值测量时间量的方法。
  • 用于 LocalDateTime 之间的比较。也可用于 Instant 之间的比较。
public class Demo08Duration {
    public static void main(String[] args) {
        // 本地日期时间对象。
        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);

        // 出生的日期时间对象
        LocalDateTime birthDate = LocalDateTime.of(2021,8,06,01,00,00);

        System.out.println(birthDate);

        Duration duration = Duration.between(today , birthDate);//第二个参数减第一个参数

        System.out.println(duration.toDays());//两个时间差的天数
        System.out.println(duration.toHours());//两个时间差的小时数
        System.out.println(duration.toMinutes());//两个时间差的分钟数
        System.out.println(duration.toMillis());//两个时间差的毫秒数
        System.out.println(duration.toNanos());//两个时间差的纳秒数
    }
}

  1. Duration: 用于计算两个“时间”间隔。
  2. Period: 用于计算两个“日期”间隔。

ChronoUnit

ChronoUnit类可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位。

public class Demo09ChronoUnit {
    public static void main(String[] args) {
        // 本地日期时间对象:此刻的
        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);

        // 生日时间
        LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,59);
        System.out.println(birthDate);

        System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
        System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
        System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
        System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
        System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
        System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
        System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
        System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
        System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
        System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
        System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
        System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
        System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
        System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
        System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));
    }
}

包装类

其实就是8种基本数据类型对应的引用类型。

基本数据类型 引用数据类型
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

为什么提供包装类?

  • Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。
  • 后面的集合和泛型其实也只能支持包装类型,不支持基本数据类型。

自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量。
自动拆箱:包装类型的变量可以直接赋值给基本数据类型的变量。

包装类的特有功能

  • 包装类的变量的默认值可以是null,容错率更高。
  • 可以把基本类型的数据转换成字符串类型(用处不大)
  1. 调用toString()方法得到字符串结果。
  2. 调用Integer.toString(基本类型的数据)。
  • 可以把字符串类型的数值转换成真实的数据类型(真的很有用)
  1. Integer.parseInt(“字符串类型的整数”)
  2. Double.parseDouble(“字符串类型的小数”)。
public class Test {
    public static void main(String[] args) {
        int a = 10;
        Integer a1 = 11;
        Integer a2 = a; // 自动装箱
        System.out.println(a);
        System.out.println(a1);

        Integer it = 100;
        int it1 = it; // 自动拆箱
        System.out.println(it1);

        double db = 99.5;
        Double db2 = db; // 自动装箱了
        double db3 = db2; // 自动拆箱
        System.out.println(db3);

        // int age = null; // 报错了!
        Integer age1 = null;
        Integer age2 = 0;

        System.out.println("-----------------");
        // 1、包装类可以把基本类型的数据转换成字符串形式。(没啥用)
        Integer i3 = 23;
        String rs = i3.toString();
        System.out.println(rs + 1);

        String rs1 = Integer.toString(i3);
        System.out.println(rs1 + 1);

        // 可以直接+字符串得到字符串类型
        String rs2 = i3 + "";
        System.out.println(rs2 + 1);

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

        String number = "23";
        //转换成整数
        // int age = Integer.parseInt(number);
        int age = Integer.valueOf(number);
        System.out.println(age + 1);

        String number1 = "99.9";
        //转换成小数
//        double score = Double.parseDouble(number1);
        double score = Double.valueOf(number1);
        System.out.println(score + 0.1);
    }
}

正则表达式

正则表达式概述、初体验

正则表示:正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性。

正则表达式初体验:

  • 需求:假如现在要求校验一个qq号码是否正确,6位及20位之内,必须全部是数字 。
  • 先使用目前所学知识完成校验需求;然后体验一下正则表达式检验。
public class RegexDemo1 {
    public static void main(String[] args) {
        System.out.println(check("2073944497"));
    }

    public static boolean check(String QQ){
        return QQ != null && QQ.matches("\\d{6,20}");
    }
}

正则表达式的匹配规则

字符串对象提供了匹配正则表达式的方法
public boolean matches​(String regex): 判断是否匹配正则表达式,匹配返回true,不匹配返回false。
字符类(默认匹配一个字符)

表达式 规则
[abc] 只能是a,b或c
[^abc] 只能是abc之外的任意字符
[a-zA-Z] 只能是a-z和A-Z范围内的
[a-d[m-p]] 只能全是a-d中或者全是m-p中
[a-z[def]] a-z和def的交集,也就是d,e或者f
[a-z[ ^bc]] a-z和除了bc的交集,也就是a-z排除bc
[a-z[ ^m-p]] a-z除了m-p

预定义的字符类(默认匹配一个字符)

表达式 规则
. 任何字符
\d 一个数字[0-9]
\D 非数字[^0-9]
\s 一个空白字符[\t\n\x0B\f\r]
\S 非空白字符[\s]
\w 英文数字下划线[a-zA-Z_0-9]
\W 一个非单词字符[^\w]

贪婪的量词(配合匹配多个字符)

表达式 规则
X? X ,一次或根本不
X* X,零次或多次
X+ X , 一次或多次
X {n} X,正好n次
X {n, } X,至少n次
X {n,m} X,至少n但不超过m次
public class RegexDemo02 {
    public static void main(String[] args) {
        //public boolean matches(String regex):判断是否与正则表达式匹配,匹配返回true
        // 只能是 a  b  c
        System.out.println("a".matches("[abc]")); // true
        System.out.println("z".matches("[abc]")); // false

        // 不能出现a  b  c
        System.out.println("a".matches("[^abc]")); // false
        System.out.println("z".matches("[^abc]")); // true

        System.out.println("a".matches("\\d")); // false
        System.out.println("3".matches("\\d")); // true
        System.out.println("333".matches("\\d")); // false
        System.out.println("z".matches("\\w")); // true
        System.out.println("2".matches("\\w")); // true
        System.out.println("21".matches("\\w")); // false
        System.out.println("你".matches("\\w")); //false
        System.out.println("你".matches("\\W")); // true
        System.out.println("---------------------------------");
        //  以上正则匹配只能校验单个字符。

        // 校验密码
        // 必须是数字 字母 下划线 至少 6位
        System.out.println("2442fsfsf".matches("\\w{6,}"));
        System.out.println("244f".matches("\\w{6,}"));

        // 验证码 必须是数字和字符  必须是4位
        System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));
        System.out.println("23_F".matches("[a-zA-Z0-9]{4}"));
        System.out.println("23dF".matches("[\\w&&[^_]]{4}"));
        System.out.println("23_F".matches("[\\w&&[^_]]{4}"));

    }

正则表达式的常见案例

public class RegexTest {
    public static void main(String[] args) {
        // 目标:校验 手机号码 邮箱  电话号码
        // checkPhone();
        // checkEmail();
        // checkTel();

        // 同学可以完成校验金额是否格式金额: 99  0.5  99.5  019   | 0.3.3

        int[] arr = {10, 4, 5,3, 4,6,  2};
        System.out.println(Arrays.binarySearch(arr, 2));

    }

    public static void checkTel(){
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请您输入您的电话号码:");
            String tel = sc.next();
            // 判断邮箱格式是否正确   027-3572457  0273572457
            if(tel.matches("0\\d{2,6}-?\\d{5,20}")){
                System.out.println("格式正确,注册完成!");
                break;
            }else {
                System.out.println("格式有误!");
            }
        }
    }

    public static void checkEmail(){
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请您输入您的注册邮箱:");
            String email = sc.next();
            // 判断邮箱格式是否正确   [email protected]
            // 判断邮箱格式是否正确   [email protected]
            // 判断邮箱格式是否正确   [email protected]
            if(email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")){
                System.out.println("邮箱格式正确,注册完成!");
                break;
            }else {
                System.out.println("格式有误!");
            }
        }
    }

    public static void checkPhone(){
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请您输入您的注册手机号码:");
            String phone = sc.next();
            // 判断手机号码的格式是否正确
            if(phone.matches("1[3-9]\\d{9}")){
                System.out.println("手机号码格式正确,注册完成!");
                break;
            }else {
                System.out.println("格式有误!");
            }
        }
    }
}

正则表达式在方法中的应用

正则表达式在字符串方法中的使用

方法名 说明
public String replaceAll(String regex,String newStr) 按照正则表达式匹配的内容进行替换
public String[] split(String regex) 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。
public class RegexDemo03 {
    public static void main(String[] args) {
        String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";

        String[] arrs = names.split("\\w+");
        for (int i = 0; i < arrs.length; i++) {
            System.out.println(arrs[i]);
        }

        String names2 = names.replaceAll("\\w+", "  ");
        System.out.println(names2);
    }
}

正则表达式爬取信息

public class RegexDemo05 {
    public static void main(String[] args) {
        String rs = "来黑马程序学习Java,电话020-43422424,或者联系邮箱" +
                "[email protected],电话18762832633,0203232323" +
                "邮箱[email protected],400-100-3233 ,4001003232";

        // 需求:从上面的内容中爬取出 电话号码和邮箱。
        // 1、定义爬取规则,字符串形式
        String regex = "(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(1[3-9]\\d{9})" +
                "|(0\\d{2,6}-?\\d{5,20})|(400-?\\d{3,9}-?\\d{3,9})";

        // 2、把这个爬取规则编译成匹配对象。
        Pattern pattern = Pattern.compile(regex);

        // 3、得到一个内容匹配器对象
        Matcher matcher = pattern.matcher(rs);

        // 4、开始找了
        while (matcher.find()) {
            String rs1 = matcher.group();
            System.out.println(rs1);
        }

    }
}

Arrays类

Arrays类概述,常用功能演示

Arrays类概述:数组操作工具类,专门用于操作数组元素的。
Arrays类的常用API:

方法名 说明
public static String toString(类型[] a) 返回数组的内容(字符串形式)
public static void sort(类型[] a) 对数组进行默认升序排序
public static void sort(类型[] a, Comparator c) 使用比较器对象自定义排序
public static int binarySearch(int[] a, int key) 二分搜索数组中的数据,存在返回索引,不存在返回-1
public class ArraysDemo1 {
    public static void main(String[] args) {
        // 目标:学会使用Arrays类的常用API ,并理解其原理
        int[] arr = {10, 2, 55, 23, 24, 100};
        System.out.println(arr);

        // 1、返回数组内容的 toString(数组)
        System.out.println(Arrays.toString(arr));

        // 2、排序的API(默认自动对数组元素进行升序排序)
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));

        // 3、二分搜索技术(前提数组必须排好序才支持,否则出bug)
        int index = Arrays.binarySearch(arr, 55);
        System.out.println(index);

        // 返回不存在元素的规律: - (应该插入的位置索引 + 1)(负数)
        int index2 = Arrays.binarySearch(arr, 22);
        System.out.println(index2);

        // 注意:数组如果没有排好序,可能会找不到存在的元素,从而出现bug!!
        int[] arr2 = {12, 36, 34, 25 , 13,  24,  234, 100};
        System.out.println(Arrays.binarySearch(arr2 , 36));
    }
}

Arrays类对于Comparator比较器的支持

Arrays类的排序方法

方法名 说明
public static void sort(类型[] a) 对数组进行默认升序排序
public static void sort(类型[] a, Comparator c) 使用比较器对象自定义排序

自定义排序规则:

  • 设置Comparator接口对应的比较器对象,来定制比较规则。

如果认为左边数据 大于 右边数据 返回正整数
如果认为左边数据 小于 右边数据 返回负整数
如果认为左边数据 等于 右边数据 返回0

public class ArraysDemo2 {
    public static void main(String[] args) {
        // 目标:自定义数组的排序规则:Comparator比较器对象。
        // 1、Arrays的sort方法对于有值特性的数组是默认升序排序
        int[] ages = {34, 12, 42, 23};
        Arrays.sort(ages);
        System.out.println(Arrays.toString(ages));

        // 2、需求:降序排序!(自定义比较器对象,只能支持引用类型的排序!!)
        Integer[] ages1 = {34, 12, 42, 23};
        /**
           参数一:被排序的数组 必须是引用类型的元素
           参数二:匿名内部类对象,代表了一个比较器对象。
         */
        Arrays.sort(ages1, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // 指定比较规则。
//                if(o1 > o2){
//                    return 1;
//                }else if(o1 < o2){
//                    return -1;
//                }
//                return 0;
                // return o1 - o2; // 默认升序
                return o2 - o1; //  降序
            }
        });
        System.out.println(Arrays.toString(ages1));

        System.out.println("-------------------------");
        Student[] students = new Student[3];
        students[0] = new Student("吴磊",23 , 175.5);
        students[1] = new Student("谢鑫",18 , 185.5);
        students[2] = new Student("王亮",20 , 195.5);
        System.out.println(Arrays.toString(students));

        // Arrays.sort(students);  // 直接运行奔溃
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                // 自己指定比较规则
                // return o1.getAge() - o2.getAge(); // 按照年龄升序排序!
                // return o2.getAge() - o1.getAge(); // 按照年龄降序排序!!
                // return Double.compare(o1.getHeight(), o2.getHeight()); // 比较浮点型可以这样写 升序
                return Double.compare(o2.getHeight(), o1.getHeight()); // 比较浮点型可以这样写  降序
            }
        });
        System.out.println(Arrays.toString(students));
    }
}

常见算法

冒泡排序

冒泡排序的思想:每次从数组中找出最大值,放到数组的后面去。

实现冒泡排序的关键步骤分析

  • 确定总共需要做几轮: 数组的长度-1.
  • 每轮比较几次:数组的长度 - i
  • 当前位置大于后一个位置则交换数据
    【Java学习笔记】常用API、Lambda、 常见算法_第2张图片

选择排序

选择排序的思想:每轮选择当前位置,开始找出后面的最小值与该位置交换。
选择排序的关键:

  • 确定总共需要选择几轮:数组长度-1
  • 控制每轮从以前位置为基准,与后面元素选择几次。
    【Java学习笔记】常用API、Lambda、 常见算法_第3张图片

二分查找

实现步骤:

  • 定义变量记录左边和右边位置。
  • 使用while循环控制查询(条件是左边位置<=右边位置)
  • 循环内部获取中间元素索引
  • 判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
  • 判断当前要找的元素如果小于中间元素,右边位置=中间索引-1
  • 判断当前要找的元素如果等于中间元素,返回当前中间元素索引。

Lambda表达式

Lambda概述

  • Lambda表达式是JDK 8开始后的一种新语法形式。
  • 作用:简化匿名内部类的代码写法。
Lambda表达式的简化格式
(匿名内部类被重写方法的形参列表) -> {
	被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义

注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式

什么是函数式接口:首先必须是接口、其次接口中有且仅有一个抽象方法的形式。

public class LambdaDemo2 {
    public static void main(String[] args) {
        // 目标:学会使用Lambda的标准格式简化匿名内部类的代码形式
        // 注意:Lambda只能简化接口中只有一个抽象方法的匿名内部类形式(函数式接口)
//        Swimming s1 = new Swimming() {
//            @Override
//            public void swim() {
//                System.out.println("老师游泳贼溜~~~~~");
//            }
//        };

//        Swimming s1 = () -> {
//            System.out.println("老师游泳贼溜~~~~~");
//        };

        Swimming s1 = () -> System.out.println("老师游泳贼溜~~~~~");
        go(s1);

        System.out.println("---------------------");
//        go(new Swimming() {
//            @Override
//            public void swim() {
//                System.out.println("学生游泳很开心~~~");
//            }
//        });

//        go(() ->{
//                System.out.println("学生游泳很开心~~~");
//        });

        go(() -> System.out.println("学生游泳很开心~~~"));
    }

    public static void go(Swimming s){
        System.out.println("开始。。。");
        s.swim();
        System.out.println("结束。。。");
    }
}

@FunctionalInterface // 一旦加上这个注解必须是函数式接口,里面只能有一个抽象方法
interface Swimming{
    void swim();
}

Lambda实战-简化常见函数式接口

public static void main(String[] args) {
	Integer[] ages = {66, 33, 22, 55, 88};
	Arrays.sort(ages, new Comparator<Integer>(){
		@Override
		public int compare(Integer o1, Integer o2) {
			return o2 - o1;
		}
	});
	System.out.println("内容:" + Arrays.toString(ages));
}

Arrays.sort(ages, (Integer o1, Integer o2) -> {
	return o2 - o1;
});


// 给登录按钮绑定点击事件监听器
btn.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("登录一下~~~");
	}
});

btn.addActionListener( (ActionEvent e) -> {
	System.out.println("登录一下~~~");
});

注意:通常我们见到的函数式接口上都有一个@FunctionalInterface注解,
标记该接口必须是满足函数式接口。

Lambda表达式的省略规则

Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化)

  • 参数类型可以省略不写。
  • 如果只有一个参数,参数类型可以省略,同时()也可以省略。
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";”不写。

你可能感兴趣的:(Java学习笔记,java,学习,算法)