Java SE基础知识详解第[10]期—常用API、Lambda、常见算法

简介: Java SE基础知识详解第[10]期—常用API、Lambda、常见算法

常用API、Lambda、常见算法

1.日期与时间

1.1Date

Date类概述

Date类的对象在Java中代表当前所在系统的日期时间信息。

Date构造器

名称

说明

public Date()

创建一个Date对象,代表的是系统当前时刻的日期时间信息

public Date(long time)

把时间毫秒值转换成Date日期对象

 

Date的常用方法

名称

说明

public long getTime()

返回从1970年1月1日 00:00:00走到此刻的总的毫秒数

public void setTime(long time)

设置日期对象的时间为当前时间毫秒值对应的时间

 

示例代码如下:

publicstaticvoidmain(String[] args) {
// 创建一个类Date类的对象,代表系统此刻日期时间对象Dated=newDate();
System.out.println(d);
// 获取时间毫秒值longtime=d.getTime();
System.out.println(time);
// System类中获取时间毫秒值的静态方法//        long time2 = System.currentTimeMillis();//        System.out.println(time2);System.out.println("--------------");
// 案例:请计算出当前时间往后走1小时121秒之后的时间是多少Dated1=newDate();
System.out.println(d1);
// 1.获取当前时间对应的毫秒值longtime2=System.currentTimeMillis();
time2+= (60*60+121) *1000;
// 2.将更改后的时间毫秒值转换为日期对象// 第一种方式:调用public Date(long time)构造器//        Date d2 = new Date(time2);//        System.out.println(d2);// 第二种方式:调用public void setTime(long time)方法d1.setTime(time2);
System.out.println(d1);
    }

1.2SimpleDateFormat

SimpleDateFormat类作用

如下图所示,可以对Date对象或时间毫秒值格式化成我们喜欢的时间形式,也可以把字符串的时间形式解析成Date对象。

SimpleDateFormat.png

SimpleDateFormat的构造器

构造器

说明

public SimpleDateFormat()

构造一个SimpleDateFormat,使用默认格式

public SimpleDateFormat(String pattern)

构造一个SimpleDateFormat,使用指定格式

SimpleDateFormat的格式化方法

格式化方法

说明

public final String format(Date date)

将日期格式化成日期/时间字符串

public final String format(Object time)

将时间毫秒值格式化成日期/时间字符串

public Date parse(String source)

从给定字符串的开始解析文本以生成日期

格式化的时间形式的常用的模式对应关系如下图所示。

DateFormat.png 

 

示例代码如下:

publicclassSimpleDateFormatDemo1 {
publicstaticvoidmain(String[] args) {
// 1.获取日期对象Dated=newDate();
System.out.println(d);
// 2.获取格式化日期对象(指定最终格式化的形式)SimpleDateFormatsdf=newSimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a"); // EEE代表取周几    a代表取上午/下午// 3.将日期对象格式化为字符串形式Stringrs=sdf.format(d); // 调用SimpleDateFormat对象中重载的format(Date date)方法,将日期转换为格式化后的日期字符串形式System.out.println(rs);
System.out.println("----------");
// 格式化日期毫秒值为字符串形式// 需求:100s后的时间是多少longtime=System.currentTimeMillis(); // 获取当前时间毫秒值time+=100*1000; // 获取100s后的时间毫秒值// 调用SimpleDateFormat对象中重载的format(Object time)方法,将时间毫秒值转换为格式化后的日期字符串形式System.out.println(sdf.format(time));
    }
}
publicclassSimpleDateFormatDemo2 {
publicstaticvoidmain(String[] args) throwsParseException {
System.out.println("------解析字符串时间------");
// 需求:请计算出 2021年08月06日11点11分11秒,往后走2天14小时49分06秒后的时间是多少// 把字符串时间拿到程序中StringdateStr="2021年08月06日 11点11分11秒";
// 把字符串时间解析为日期对象SimpleDateFormatsdf=newSimpleDateFormat("yyyy年MM月dd日 HH点mm分ss秒"); // 格式必须与被解析的字符串时间形式一模一样,否则运行时解析会出现错误Dated=sdf.parse(dateStr);
// 时间毫秒值向后走2天14小时49分06秒longtime=d.getTime() + (2L*24*60*60+14*60*60+49*60+6) *1000; // 默认是int型的计算,有可能会发生数据越界,因此在第一个数字后加L,使数据在进行运算时自动转换为long型// 将时间毫秒值格式化为字符串时间StringdateStr2=sdf.format(time);
System.out.println(dateStr2);
    }
}

注:SimpleDateFormat解析字符串时间成为日期对象,在进行SimpleDateFormat构造器声明的时候,格式必须与被解析的字符串时间形式一模一样,否则运行时解析会出现错误。

练习:秒杀活动

需求:某购物网站举办秒杀活动,开始时间2020年11月11日 0:0:0、结束时间2020年11月11日 0:10:0,当前活动结束后,系统记录到2位用户的付款时间分别如下:

小贾下单并付款的时间为:2020年11月11日 0:03:47

小皮下单并付款的时间为:2020年11月11日 0:10:11

规则:顾客的付款时间必须在秒杀时间之内,请判断出两位顾客是否秒杀成功

分析:

把4个字符串形式的时间解析成日期对象。

判断小贾和小皮的时间是否在秒杀时间范围之内,并给出相应的提示。

示例代码如下:

publicclassSimpleDateFormatTest3 {
publicstaticvoidmain(String[] args) throwsParseException {
/**需求:某购物网站举办秒杀活动,开始时间2020年11月11日 0:0:0、结束时间2020年11月11日 0:10:0,当前活动结束后,系统记录到2位用户的付款时间分别如下:小贾下单并付款的时间为:2020年11月11日 0:03:47小皮下单并付款的时间为:2020年11月11日 0:10:11规则:顾客的付款时间必须在秒杀时间之内,请判断出两位顾客是否秒杀成功*/StringstartDateStr="2020年11月11日 0:0:0"; // 秒杀开始时间StringendDateStr="2020年11月11日 0:10:0"; // 秒杀结束时间StringjiaDateStr="2020年11月11日 0:03:47"; // 小贾付款时间StringpiDateStr="2020年11月11日 0:10:11"; // 小皮付款时间时间// 调用判断是否抢购成功的方法isPaySuccess(startDateStr, endDateStr, jiaDateStr);
isPaySuccess(startDateStr, endDateStr, piDateStr);
    }
// 判断是否抢购成功publicstaticvoidisPaySuccess(StringstartDateStr, StringendDateStr, StringpayDateStr) throwsParseException {
// 把字符串时间解析为日期对象SimpleDateFormatsdf=newSimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
DatestartDate=sdf.parse(startDateStr);
DateendDate=sdf.parse(endDateStr);
DatepayDate=sdf.parse(payDateStr);
// 判断付款时间是否在规定时间内,并给出相应提示if (payDate.before(startDate)) {
System.out.println("未到抢购时间");
        } elseif ((payDate.after(startDate)) & (payDate.before(endDate))) {
System.out.println("抢购成功!");
        } else {
System.out.println("抢购时间已过!");
        }
    }
}

1.3Calendar

Calendar概述

Calendar代表了系统此刻日期对应的日历对象

Calendar是一个抽象类,不能直接创建对象。

Calendar常用方法

方法名

说明

public static Calendar getInstance()

获取当前日历对象

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()

拿到此刻时间毫秒值

 

示例代码如下:

publicstaticvoidmain(String[] args) {
// 1.public static Calendar getInstance()   获取当前日历对象Calendarcal=Calendar.getInstance();
System.out.println(cal);
// 2.public int get(int field)  取日期中的某个字段信息intyear=cal.get(Calendar.YEAR);
System.out.println(year);
intmonth=cal.get(Calendar.MONTH) +1; // 月份是从0开始计算,因此真实月份需要在日历中取出来的基础上 + 1System.out.println(month);
intday=cal.get(Calendar.DATE);
System.out.println(day);
intdays=cal.get(Calendar.DAY_OF_YEAR); // 一年中的第几天System.out.println(days);
// 3.public void set(int field,int value)   修改日历的某个字段信息//        cal.set(Calendar.HOUR, 7); // 将日历中的时间修改为7点(12小时制,分上午/下午,如果输入12-24会顺延计算)//        System.out.println(cal.get(Calendar.HOUR));// 4.public void add(int field,int amount)  为某个字段增加/减少指定的值cal.add(Calendar.DATE, 5); // 将日历中的日期增加5天System.out.println(cal.get(Calendar.DATE));
// 5.public final Date getTime()    拿到此刻日期对象Datedate=cal.getTime();
System.out.println(date); // 当前日期对象,Date类型  Date d = new Date();   long time = d.getTime(); 获取的是当前时刻对应的毫秒值,long类型// 6.public long getTimeInMillis()  拿到此刻时间毫秒值longtime=cal.getTimeInMillis();
System.out.println(time);
    }
}

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

2.JDK8新增日期类

2.1概述

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

LocalDate:不包含具体时间的日期。

LocalTime:不含日期的时间。

LocalDateTime:包含了日期及时间。

Instant:代表的是时间戳。

DateTimeFormatter 用于做时间的格式化和解析。

Duration:用于计算两个“时间”间隔。

Period:用于计算两个“日期”间隔。

新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便。

新API的类型几乎全部是不变类型(和String的使用类似),可以放心使用不必担心被修改。

2.2LocalTime /LocalDate / LocalDateTime

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

LocalDate、LocalTime、LocalDateTime构建对象

方法名

说明

 

public static Xxxx.now();

静态方法,根据当前时间创建对象

LocaDate localDate = LocalDate.now();

LocalTime llocalTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now();

public static Xxxx.of(…);

静态方法,指定日期/时间创建对象

LocalDate localDate1=LocalDate.of(2099, 11, 11);

LocalTime localTime1 = LocalTime.of(11, 11, 11);

LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);

 

LocalDateTime的转换API

方法名

说明

public LocalDate toLocalDate()

转换成一个LocalDate对象

public LocalTime toLocalTime()

转换成一个LocalTime对象

 

修改相关的API

LocalDateTime 综合了LocalDate和LocalTime 里面的方法,所以下面只用LocalDate和LocalTime来举例。

修改相关的API

方法名

说明

plusDays, plusWeeks, plusMonths, plusYears

向当前 LocalDate 对象添加几天、几周、几个月、几年

minusDays,minusWeeks,minusMonths, minusYears

从当前 LocalDate 对象减去几天、几周、几个月、几年

withDayOfMonth, withDayOfYear, withMonth, withYear

将月份天数、年份天数、月份、年份修改为指定的值并返回新的LocalDate对象

isBefore, isAfter

比较两个 LocalDate对象

 

注:LocalDateTime、LocalDate、LocalTime都是不可变的,因此这些方法返回的是一个新的对象原LocalDateTime、LocalDate、LocalTime对象中存储时刻不变。

2.3Instant

JDK8获取时间戳特别简单,且功能更丰富。

如下图所示,Instant类由一个静态的工厂方法now()可以返回当前时间戳。时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是类似JDK8 以前的Date。

Instant和Date这两个类可以进行转换。

Instant.png

2.4DateTimeFormatter

在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。

调用format方法与解析字符串时间为日期时间对象方法如下图所示,其中format方法正反都能调用。

DateTimeFormatter.png

DateTimeFormatterOfPattern.png

2.5Period/Duration

Period

如下图所示,在Java8中,我们可以使用以下类来计算日期间隔差异:java.time.Period

主要是 Period 类方法 getYears(),getMonths() 和 getDays() 来计算,只能精确到年月日用于 LocalDate 之间的比较

Period.png

Duration

如下图所示,在Java8中,我们可以使用以下类来计算时间间隔差异:java.time.Duration

提供了使用基于时间的值测量时间量的方法,用于 LocalDateTime 之间的比较,也可用于 Instant 之间的比较。

Duration.png

注:Period是比较两个时间差xx年xx月xx天(满量程会进一),如2021.年1月1日至2022年1月10日,period.getYears()为1,period.getMonths()为0,period.getDays()为9,最终结果是三者的结合。

Duration是比较两个时间差多少具体时间,如2022年1月10日 0:00:00至2022年1月10日 1:06:07,duration.toHours()为1,duration.toMinutes()为66,duration.toMillis()为3967000,分别计算

2.6ChronoUnit

java.time.temporal.ChronoUnit

如下图所示,ChronoUnit类可用于测量两个时刻的时间间隔,这个工具类是最全的了,可以用于比较所有的时间单位

ChronoUnit.png 

3.包装类

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

基本数据类型与引用数据类型的对应关系

基本数据类型

引用数据类型

byte

Byte

short

Short

int

Integer

long

Long

char

Character

float

Float

double

Double

boolean

Boolean

 

为什么提供包装类?

Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。

后面的集合和泛型也只能支持包装类型,不支持基本数据类型

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

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

包装类的特有功能

包装类的变量的默认值可以是null,容错率更高。

可以把基本类型的数据转换成字符串类型(用处不大)

①调用toString()方法得到字符串结果

②调用Integer.toString(基本类型的数据)

把字符串类型的数值转换成真实的数据类型

① Integer.parseInt(“字符串类型的整数”)

② Double.parseDouble(“字符串类型的小数”)

也可以用valueOf()方法代替以上两个方法,谁调的方法就转成谁的类型

示例代码如下:

publicstaticvoidmain(String[] args) {
inta=10;
Integera1=11;
Integera2=a; // 自动装箱inta3=a1; // 自动拆箱System.out.println(a2); // 10System.out.println(a3); // 11//        int age = null; // 报错,null是引用类型的取值,基本类型不支持Integerage=null;
System.out.println("--------");
// 包装类可以把基本数据类型的数据转换为字符串形式Integeri=23;
Stringrs=i.toString(); // 调用toString()方法得到字符串结果System.out.println(rs+1); // 231 " + " 在字符串运算中作连接符Stringrs2=Integer.toString(i); // 调用Integer.toString(基本类型的数据)// 把字符串类型的数值转换成真实的数据类型Stringnumber="123";
System.out.println(number+1); // 1231 number为String引用数据类型,做连接intnumber2=Integer.parseInt(number);
System.out.println(number2+1); // 124 number2为基本数据类型,做求和计算Stringscore="99.5";
System.out.println(score+0.5); // 99.50.5doublescore2=Double.parseDouble(score);
System.out.println(score2+0.5); // 100.0// 也可以用valueOf()方法代替以上两个方法,谁调的方法就转成谁的类型intnumber3=Integer.valueOf(number);
System.out.println(number3);
doublescore3=Double.valueOf(score);
System.out.println(score3);
    }

4.正则表达式

正则表示

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

需求:假如现在要求校验一个qq号码是否正确,6位及20位之内,必须全部是数字。先使用目前所学知识完成校验需求,然后使用正则表达式检验。

示例代码如下:

 

publicstaticvoidmain(String[] args) {
System.out.println(checkQQ(null)); // falseSystem.out.println(checkQQ("")); // falseSystem.out.println(checkQQ("12345678")); // trueSystem.out.println(checkQQ("123456789876543210123456")); // falseSystem.out.println("------正则表达式------");
System.out.println(checkQQ2(null)); // falseSystem.out.println(checkQQ2("")); // falseSystem.out.println(checkQQ2("12345678")); // trueSystem.out.println(checkQQ2("123456789876543210123456")); // false    }
publicstaticbooleancheckQQ(Stringqq) {
// 判断QQ号码长度是否符合要求if (qq==null||qq.length() <6||qq.length() >20) {
returnfalse;
        }
// 判断qq号码是否全部为数字for (inti=0; i<qq.length(); i++) {
// 获取每一位字符charch=qq.charAt(i);
// 判断该字符是否是数字if (ch<'0'||ch>'9') { // 因为字符型每个字符都有对应的ASCⅡ编号,在比较数值大小时要与实际值对应的编号(而不是实际值作为编号)进行比较,因此要带单引号returnfalse;
            }
        }
returntrue;
    }
// 正则表达式publicstaticbooleancheckQQ2(Stringqq) {
returnqq!=null&&qq.matches("\\d{6,20}");
    }

字符串对象提供了匹配正则表达式的方法

public boolean matches (String regex):判断是否匹配正则表达式,匹配返回true,不匹配返回false

正则表达式书写规则如下图所示。

Regex.png

其中X代表正则表达式。

示例代码如下:

publicstaticvoidmain(String[] args) {
// 判断是否为数字、字母、下划线、至少6位System.out.println("dasdsad1232".matches("\\w{6,}")); // trueSystem.out.println("25F8".matches("\\w{6,}")); // falseSystem.out.println("-----------");
// 判断是否为数字、字母,四位System.out.println("Q".matches("[a-zA-Z0-9]")); // trueSystem.out.println("29fQ".matches("[a-zA-Z0-9]{4}")); // true   校验多个字符的字符串必须要加上贪婪的量词System.out.println("29_Q".matches("[a-zA-Z0-9]{4}")); // falseSystem.out.println("29fQ".matches("[\\w&&[^_]]{4}")); // trueSystem.out.println("29_Q".matches("[\\w&&[^_]]{4}")); // false    }

注:校验多个字符的字符串必须要加上贪婪的量词。

案例

需求:

①请编写程序模拟用户输入手机号码、验证格式正确,并给出提示,直到格式输入正确为止。

②请编写程序模拟用户输入邮箱号码、验证格式正确,并给出提示,直到格式输入正确为止。

③请编写程序模拟用户输入电话号码、验证格式正确,并给出提示,直到格式输入正确为止。

分析:

定义方法,接收用户输入的数据,使用正则表达式完成检验,并给出提示。

示例代码如下:

publicclassRegexTest3 {
publicstaticvoidmain(String[] args) {
Scannersc=newScanner(System.in);
//        // 校验手机号//        boolean phoneNumberIsRight = false;//        while (phoneNumberIsRight == false) {//            System.out.println("请输入手机号:");//            String phoneNumber = sc.next();//            phoneNumberIsRight = checkPhone(phoneNumber);//        }//        // 校验邮箱号//        boolean EmailIsRight = false;//        while (EmailIsRight == false) {//            System.out.println("请输入邮箱号:");//            String Email = sc.next();//            EmailIsRight = checkEmail(Email);//        }// 校验电话号booleantelIsRight=false;
while (telIsRight==false) {
System.out.println("请输入电话号:");
Stringtel=sc.next();
telIsRight=checkTel(tel);
        }
    }
/*** create by: 全聚德在逃烤鸭、* description: 校验手机号* create time: 2022/4/22 0022 9:23** @param phoneNumber* @return boolean*/publicstaticbooleancheckPhone(StringphoneNumber) {
// 判断手机号码的格式是否正确// 电话号码格式 "1" + 3-9的数字 + 9位数字if (phoneNumber.matches("1[3-9]\\d{9}")) { // 第一位为1,第二位为3-9其中之一,剩下的为9位的数字System.out.println("手机号码格式正确");
returntrue;
        } else {
System.out.println("手机号码格式错误,请重新输入!");
returnfalse;
        }
    }
/*** create by: 全聚德在逃烤鸭、* description: 校验邮箱号* create time: 2022/4/22 0022 9:39** @param Email* @return boolean*/publicstaticbooleancheckEmail(StringEmail) {
// 判断邮箱的格式是否正确/*主要邮箱格式类型215435412@qq.coms21545rFf25@163.comfaf454rRF@sff.com.cn*/// 判断条件:分为4部分:// 第一部分:1-30位的任意大小写字母、数字、下划线// 第二部分:@// 第三部分:2-20位的任意大小写字母、数字// 第四部分:1-2次的("." + 2-20位的任意大小写字母、数字)   不能直接写".",会当作任意字符if (Email.matches("\\w{1,30}@[\\w&&[^_]]{2,20}(\\.[\\w&&[^_]]{2,20}){1,2}")) {
System.out.println("邮箱格式正确");
returntrue;
        } else {
System.out.println("邮箱格式错误,请重新输入!");
returnfalse;
        }
    }
/*** create by: 全聚德在逃烤鸭、* description: 校验电话号码* create time: 2022/4/22 0022 9:42** @param tel* @return boolean*/publicstaticbooleancheckTel(Stringtel) {
// 判断电话号码的格式是否正确// 电话号码格式 "0" + 2-3位的数字 + -(可有可无) + 5-20位数字if (tel.matches("0\\d{2,3}-?\\d{5,20}")) { // 第一位为1,第二位为3-9其中之一,剩下的为9位的数字System.out.println("电话号码格式正确");
returntrue;
        } else {
System.out.println("电话号码格式错误,请重新输入!");
returnfalse;
        }
    }
}

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

方法名

说明

public String replaceAll(String regex,String newStr)

按照正则表达式匹配的内容进行替换

public String[] split(String regex)

按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。

 

示例代码如下:

publicstaticvoidmain(String[] args) {
// 1.   public String replaceAll(String regex,String newStr)    按照正则表达式匹配的内容进行替换Stringstr="光明小学424sds_f二年级faf_s45_45SDA一班d45F";
StringstrNew=str.replaceAll("\\w+", " "); // 将大小写字母、数字、下划线替换为空格System.out.println(strNew); // 光明小学 二年级 一班 // 2.   public String[] split(String regex) 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组Stringname="张三sraga89f李四sf546af王五";
String[] names=name.split("\\w+");
System.out.print("[");
for (inti=0; i<names.length; i++) {
System.out.print(i==names.length-1?names[i] : names[i] +",");
        }
System.out.println("]"); // [张三,李四,王五]    }

5.Arrays类

Arrays类概述

数组操作工具类,专门用于操作数组元素的。

Arrays常用API

方法名

说明

public static String toString(类型[] a)

返回数组的内容(字符串形式)

public static void sort(类型[] a)

对数组进行默认升序排序

public static <T> void sort(类型[] a, Comparator<? super T> c)

使用比较器对象自定义排序

public static int binarySearch(int[] a, int key)

二分搜索(前提是数组必须排好序)数组中的数据,存在返回索引,不存在返回-(应该插入位置的索引 + 1)

 

自定义排序规则

设置Comparator接口对应的比较器对象,来定制比较规则比较规则如下图所示

ComparatorRule.png

示例代码如下:

Student类

publicclassStudent {
privateStringname;
privateintage;
privatedoubleheight;
publicStudent() {
    }
publicStudent(Stringname, intage, doubleheight) {
this.name=name;
this.age=age;
this.height=height;
    }
@OverridepublicStringtoString() {
return"Student{"+"name='"+name+'\''+", age="+age+", height="+height+'}';
// getter、setter}

测试类

publicclassArraysDemo1 {
publicstaticvoidmain(String[] args) {
// 1.   public static String toString(类型[] a)   返回数组的内容(字符串形式)int[] arr= {10, 20, 33, 84, 63};
System.out.println(arr); // [I@1540e19dStringrs=Arrays.toString(arr);
System.out.println(rs); // [10, 20, 33, 84, 63]//2.    public static void sort(类型[] a) 对数组进行默认升序排序Arrays.sort(arr); // 对数组进行默认升序排序System.out.println(Arrays.toString(arr)); // [10, 20, 33, 63, 84]//3.    public static int binarySearch(int[] a, int key)    二分搜索(前提是数组必须排好序)数组中的数据,存在返回索引,不存在返回-(应该插入位置的索引 + 1)intindex=Arrays.binarySearch(arr, 63); // 使用二分搜索查找63System.out.println(index); // 3intindex2=Arrays.binarySearch(arr, 99); // 使用二分搜索查找90System.out.println(index2); // -6intindex3=Arrays.binarySearch(arr, 19); // 使用二分搜索查找90System.out.println(index3); // -2// 4.public static <T> void sort(类型[] a, Comparator<? super T> c)   使用比较器对象自定义排序// Arrays的sort方法对于默认有值特性的数组是升序排序// 自定义规则排序(自定义比较器对象,只能支持引用类型的排序)Integer[] ages= {34, 12, 42, 23};
/*参数一:被排序的数组,必须是引用数据类型参数二:匿名内部类对象,代表一个比较器对象*/Arrays.sort(ages, newComparator<Integer>() {
@Override// 若返回正整数,则将o1排到后面,若返回负整数,则将o2排到后面publicintcompare(Integero1, Integero2) {
// 自定义比较规则returno2-o1; // 降序排序            }
        });
System.out.println(Arrays.toString(ages)); // [42, 34, 23, 12]System.out.println("--------------");
// 对自定义类型数组进行排序Student[] students=newStudent[3];
students[0] =newStudent("张三", 18, 185.3);
students[1] =newStudent("李四", 22, 180.5);
students[2] =newStudent("王五", 17, 173.5);
System.out.println(Arrays.toString(students));
// [Student{name='张三', age=18, height=185.3}, Student{name='李四', age=22, height=180.5}, Student{name='王五', age=17, height=173.5}]Arrays.sort(students, newComparator<Student>() {
@Overridepublicintcompare(Studento1, Studento2) {
returno1.getAge() -o2.getAge(); // 按年龄升序排序//                return Double.compare(o1.getHeight(), o2.getHeight()); // 按身高升序排序(double类型差值有可能不为整数,但返回值要求必须为整数,可以调用Double类中的compare()方法进行比较,返回整数)            }
        });
System.out.println(Arrays.toString(students));
// [Student{name='王五', age=17, height=173.5}, Student{name='张三', age=18, height=185.3}, Student{name='李四', age=22, height=180.5}]    }
}

注:Comparator排序规则,若返回正整数,则将o1排到后面,若返回负整数,则将o2排到后面。

6.常选择排序见算法

6.1选择排序的思想

如下图所示,每轮选择当前位置,开始找出后面的较小值与该位置交换。

SelectSort.png

选择排序的关键

①确定总共需要选择几轮: 数组的长度-1。

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

示例代码如下:

publicstaticvoidmain(String[] args) {
// 定义数组int[] arr= {5, 1, 3, 2};
// 定义循环,控制选择几轮  arr.length - 1inttemp; // 临时变量,由于交换数据时临时存储数据for (inti=0; i<arr.length-1; i++) {
// 定义内部循环,控制每轮比较几次for (intj=i+1; j<arr.length; j++) {
// 判断是否有比当前第i位数字值更小的数字if (arr[j] <arr[i]) { // 若存在,则交换二者位置temp=arr[i];
arr[i] =arr[j];
arr[j] =temp;
                }
            }
        }
System.out.println(Arrays.toString(arr)); // [1, 2, 3, 5]    }

6.2二分搜索

二分搜索(前提是数组必须升序排好)数组中的数据,存在返回索引,不存在返回-(应该插入位置的索引 + 1)

数组二分搜索的实现步骤:

①定义变量记录左边和右边位置;

②使用while循环控制查询(条件是左边位置<=右边位置);

③循环内部获取中间元素索引;

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

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

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

示例代码如下:

publicclassBinarySearch {
publicstaticvoidmain(String[] args) {
// 定义数组int[] arr= {10, 14, 16, 25, 28, 30, 35, 80, 100};
//    0   1   2   3   4   5   6   7   8System.out.println(binarySearch(arr, 10)); // 0System.out.println(binarySearch(arr, 30)); // 5System.out.println(binarySearch(arr, 18)); // -1System.out.println(binarySearch(arr, 150)); // -1    }
/*** create by: 全聚德在逃烤鸭、* description: 数组二分搜索排序* create time: 2022/4/30 0030 10:07** @param arr  被搜索的数组* @param data 搜索的数据* @return int    搜索数据对应索引/-1*/publicstaticintbinarySearch(int[] arr, intdata) {
// 定义左边位置和右边位置intleft=0;
intright=arr.length-1;
// 定义循环,二分搜索while (left<=right) {
// 取中间位置索引intmiddleIndex= (right+left) /2;
// 比较当前中间索引位置数据值与搜索的数据值的大小if (arr[middleIndex] ==data) { // 若相等,则说明找到该元素,将中间位置索引返回returnmiddleIndex;
            } elseif (arr[middleIndex] >data) { // 当前中间索引位置数据值大于搜索的数据值,说明搜索元素在当前中间位置左侧,则舍弃当前中间索引位置右边部分,重新搜索right=middleIndex-1;
            } else { // 当前中间索引位置数据值小于搜索的数据值,说明搜索元素在当前中间位置右侧,则舍弃当前中间索引位置左边部分,重新搜索left=middleIndex+1;
            }
        }
return-1; // 说明搜索完毕,未找到对应数据,返回-1    }
}

7.Lambda表达式

Lambda概述

Lambda表达式是JDK 8开始后的一种新语法形式。

作用:简化匿名内部类的代码写法。

Lambda表达式的简化格式如下图所示。

Lambda.png

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

什么是函数式接口?

必须是接口,接口中有且仅有一个抽象方法的形式。

通常会在接口上方加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口

示例代码如下:

publicclassLambdaDemo1 {
publicstaticvoidmain(String[] args) {
Swimmings1=newSwimming() {
@Overridepublicvoidswim() {
System.out.println("学生游泳");
            }
        };
go(s1);
System.out.println("---------");
// 使用Lambda表达式简化函数式接口的匿名内部类的写法形式go(() -> {
System.out.println("老师游泳");
        });
    }
publicstaticvoidgo(Swimmings) {
System.out.println("开始游泳");
s.swim();
System.out.println("结束游泳");
    }
}
@FunctionalInterface// 加上此注解,代表接口是函数式接口,里面有且只有一个抽象方法interfaceSwimming {
publicvoidswim();
}

Lambda的好处?

Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁、更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。

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

参数类型可以省略不写

②如果只有一个参数,参数类型可以省略,同时()也可以省略不写

③如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号

④如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写。

相关文章
|
4天前
|
Java API Apache
ZooKeeper【基础 03】Java 客户端 Apache Curator 基础 API 使用举例(含源代码)
【4月更文挑战第11天】ZooKeeper【基础 03】Java 客户端 Apache Curator 基础 API 使用举例(含源代码)
23 11
|
5天前
|
安全 Java API
java借助代理ip,解决访问api频繁导致ip被禁的问题
java借助代理ip,解决访问api频繁导致ip被禁的问题
|
8天前
|
存储 安全 Java
说说Java 8 引入的Stream API
说说Java 8 引入的Stream API
11 0
|
8天前
|
分布式计算 Java API
Java 8新特性之Lambda表达式与Stream API
【4月更文挑战第16天】本文将介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁、易读。Stream API是Java 8中引入的一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而使代码更加简洁、高效。本文将通过实例代码详细讲解这两个新特性的使用方法和优势。
|
9天前
|
安全 Java API
RESTful API设计与实现:Java后台开发指南
【4月更文挑战第15天】本文介绍了如何使用Java开发RESTful API,重点是Spring Boot框架和Spring MVC。遵循无状态、统一接口、资源标识和JSON数据格式的设计原则,通过创建控制器处理HTTP请求,如示例中的用户管理操作。此外,文章还提及数据绑定、验证、异常处理和跨域支持。最后,提出了版本控制、安全性、文档测试以及限流和缓存的最佳实践,以确保API的稳定、安全和高效。
|
12天前
|
存储 Java 关系型数据库
掌握Java 8 Stream API的艺术:详解流式编程(一)
掌握Java 8 Stream API的艺术:详解流式编程
46 1
|
21天前
|
前端开发 Java API
构建RESTful API:Java中的RESTful服务开发
【4月更文挑战第3天】本文介绍了在Java环境中构建RESTful API的重要性及方法。遵循REST原则,利用HTTP方法处理资源,实现CRUD操作。在Java中,常用框架如Spring MVC简化了RESTful服务开发,包括定义资源、设计表示层、实现CRUD、考虑安全性、文档和测试。通过Spring MVC示例展示了创建RESTful服务的步骤,强调了其在现代Web服务开发中的关键角色,有助于提升互操作性和用户体验。
构建RESTful API:Java中的RESTful服务开发
|
22天前
|
搜索推荐 Java
Java基础(快速排序算法)
Java基础(快速排序算法)
23 4
|
30天前
|
Java 数据库连接 API
Java 学习路线:基础知识、数据类型、条件语句、函数、循环、异常处理、数据结构、面向对象编程、包、文件和 API
Java 是一种广泛使用的、面向对象的编程语言,始于1995年,以其跨平台性、安全性和可靠性著称,应用于从移动设备到数据中心的各种场景。基础概念包括变量(如局部、实例和静态变量)、数据类型(原始和非原始)、条件语句(if、else、switch等)、函数、循环、异常处理、数据结构(如数组、链表)和面向对象编程(类、接口、继承等)。深入学习还包括包、内存管理、集合框架、序列化、网络套接字、泛型、流、JVM、垃圾回收和线程。构建工具如Gradle、Maven和Ant简化了开发流程,Web框架如Spring和Spring Boot支持Web应用开发。ORM工具如JPA、Hibernate处理对象与数
92 3
|
1月前
|
分布式计算 Java 程序员
Java 8新特性之Lambda表达式与Stream API
本文将详细介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种简洁、匿名的函数表示方法,它允许我们将函数作为参数传递给其他方法。而Stream API则是一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而提高代码的可读性和可维护性。通过本文的学习,你将能够掌握Lambda表达式和Stream API的基本用法,以及如何在项目中应用这两个新特性。
31 10