常用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的构造器
构造器 |
说明 |
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) |
从给定字符串的开始解析文本以生成日期 |
格式化的时间形式的常用的模式对应关系如下图所示。
示例代码如下:
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这两个类可以进行转换。
2.4DateTimeFormatter
在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。
调用format方法与解析字符串时间为日期时间对象方法如下图所示,其中format方法正反都能调用。
2.5Period/Duration
Period
如下图所示,在Java8中,我们可以使用以下类来计算日期间隔差异:java.time.Period
主要是 Period 类方法 getYears(),getMonths() 和 getDays() 来计算,只能精确到年月日,用于 LocalDate 之间的比较。
Duration
如下图所示,在Java8中,我们可以使用以下类来计算时间间隔差异:java.time.Duration
提供了使用基于时间的值测量时间量的方法,用于 LocalDateTime 之间的比较,也可用于 Instant 之间的比较。
注: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类可用于测量两个时刻的时间间隔,这个工具类是最全的了,可以用于比较所有的时间单位。
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。
正则表达式书写规则如下图所示。
其中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接口对应的比较器对象,来定制比较规则,比较规则如下图所示。
示例代码如下:
Student类
publicclassStudent { privateStringname; privateintage; privatedoubleheight; publicStudent() { } publicStudent(Stringname, intage, doubleheight) { this.name=name; this.age=age; this.height=height; } publicStringtoString() { 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>() { // 若返回正整数,则将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>() { publicintcompare(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选择排序的思想
如下图所示,每轮选择当前位置,开始找出后面的较小值与该位置交换。
选择排序的关键
①确定总共需要选择几轮: 数组的长度-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表达式只能简化函数式接口的匿名内部类的写法形式。
什么是函数式接口?
必须是接口,接口中有且仅有一个抽象方法的形式。
通常会在接口上方加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口。
示例代码如下:
publicclassLambdaDemo1 { publicstaticvoidmain(String[] args) { Swimmings1=newSwimming() { publicvoidswim() { System.out.println("学生游泳"); } }; go(s1); System.out.println("---------"); // 使用Lambda表达式简化函数式接口的匿名内部类的写法形式go(() -> { System.out.println("老师游泳"); }); } publicstaticvoidgo(Swimmings) { System.out.println("开始游泳"); s.swim(); System.out.println("结束游泳"); } } // 加上此注解,代表接口是函数式接口,里面有且只有一个抽象方法interfaceSwimming { publicvoidswim(); }
Lambda的好处?
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁、更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。
Lambda表达式的省略写法(在Lambda表达式的基础上进一步简化)
①参数类型可以省略不写。
②如果只有一个参数,参数类型可以省略,同时()也可以省略不写。
③如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号。
④如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写。