一、JDK8新特性
1.Lambda表达式
Lambda表达式是JDK 8开始新增的一种语法形式;作用:用于简化名内部类的代码写法。
注意:Lambda表达式并不是说能简化全部匿名内部类的写法,只能简化函数式接口的匿名内部类。
- 有且仅有一个抽象方法的接口。
- 注意:将来我们见到的大部分函数式接口,上面都可能会有@Functionalinterface的注解,有该注解:的接口就必定是函数式接口。
package com.API;
public class LambdaTest {
public static void main(String[] args) {
Animal a = new Animal() {
@Override
public void run() {
System.out.println("汪汪队立大功!");
}
};
a.run();
//对于类无法使用lambda函数的
Swim s = new Swim() {
@Override
public void swim() {
System.out.println("小鲤鱼历险记!");
}
};
s.swim();
Swim s1 = () -> {
System.out.println("小鲤鱼历险记2!");
};
s1.swim();
}
}
abstract class Animal {
public abstract void run();
}
interface Swim {
void swim();
}
2.Lambda表达式省略规则
- 参数类型可以省略不写。
- 如果只有一个参数,参数类型可以省略,同时()也可以省略。
- 如果Lambda表达式中的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!此时,如果这行代码是return语句,也必须去掉return不写。
Arrays.setAll(prices,value->prices[value]*0.8);
3.方法引用
3.1静态方法的引用
静态方法的引用
类名::静态方法。
使用场景
- 如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用。
3.2实例方法的引用
实例方法的引用
对象名::实例方法。
使用场景
如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用。
package com.API;
import java.util.Arrays;
public class ArrayTest1 {
public static void main(String[] args) {
Student[] students =new Student[4];
students[0]=new Student("蜘姝精",23);
students[1]=new Student( "紫假", 26);
students[2]=new Student( "紫霞",26);
students[3]=new Student( "至蓉宝",24);
//静态方法引用
Arrays.sort(students,CompareByData::compareInt);
System.out.println(Arrays.toString(students));
//实例方法引用
CompareByData compareByData = new CompareByData();
Arrays.sort(students,compareByData::compareByAge);
System.out.println(Arrays.toString(students));
}
}
class Student implements Comparable<Student>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return this.age-o.age;
}
}
class CompareByData{
public static int compareInt(Student o1,Student o2){
return o1.getAge()-o2.getAge();
}
public int compareByAge(Student o1,Student o2){
return o2.getAge()-o1.getAge();
}
}
3.3特定类型方法的引用
特定类型的方法引用
类型::方法。
使用场景
如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用
Arrays.sort(names,String::compareToIgnoreCase);
3.4构造器引用
类名::new。
使用场景
如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用
二、常见算法
解决某个实际问题的过程和方法!
2.1 冒泡排序
每次从数组中找出最大值放在数组的后面去。
import java.util.Arrays;
public class Sort1 {
public static void main(String[] args) {
int[] arr = {5, 2, 3, 1};
//控制轮数
for (int i = 0; i < arr.length - 1; i++) {
//i=0 1 2 [5, 2, 3, 1] 次数
//i=0 第一轮 0 1 2 3
//i=1 第二轮 0 1 2
//i=2 第三轮 0 1
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));
}
}
2.2 选择排序
每轮选择当前位置,开始找出后面的较小值与该位置交换
import java.util.Arrays;
public class Sort2 {
public static void main(String[] args) {
//1.准备好一个数组
int[] arr = {5, 2, 3, 1};
//2.控制轮数
for (int i = 0; i < arr.length - 1; i++) {
//i=0 j=1 2 3
//i=1 j=2 3
//i=2 j=3
//每轮选择几次
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));
}
}
优化
import java.util.Arrays;
public class Sort2 {
public static void main(String[] args) {
//1.准备好一个数组
int[] arr = {5, 2, 3, 1};
//2.控制轮数
for (int i = 0; i < arr.length - 1; i++) {
//i=0 j=1 2 3
//i=1 j=2 3
//i=2 j=3
int minIndex = i;
//每轮选择几次
for (int j = i + 1; j < arr.length; j++) {
if (arr[minIndex] > arr[j]) {
minIndex = j;
}
}
if (i != minIndex) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
2.3 查找算法
基本查找,顺序查找
注意:在数据量特别大的时候,基本查找这种从前往后挨个找的形式,性能是很差的!
二分查找(折半查找)
- 前提条件:数组中的数据必须是有序的。
- 核心思想:每次排除一半的数据,查询数据的性能明显提高极多!
- 结论:二分查找正常的折半条件应该是开始位置left<=结束位置right
public class Sort3 {
public static void main(String[] args) {
int[] a={7,23,79,81,103,127,131,147};
System.out.println(binarySearch(a,81));
}
public static int binarySearch(int[] a,int data){
//1、定义两个交量,一手站在左边位置,一个站在右边位置
int left=0;
int right=a.length-1;
//2. 定义一个循环控制
while (left<=right){
//3.每次折半计算中间位置
int mid=(left+right)/2;
//4.判断当前要找的元素值,与中间位置处的元素值的大小情况。
if(a[mid]>data){
right=mid-1;
}else if(a[mid]<data){
left=mid+1;
}else {
return mid;
}
}
return -1;
}
}
三、正则表达式
就是由一些特定的字符组成,代表的是一个规则
- 用来校验数据格式是否合法
- 在一段文本中查找满足要求的内容
public class RegexTest1 {
public static void main(String[] args) {
String s="1349281263";
boolean b = checkQQ(s);
System.out.println(b);
System.out.println(RegexQQ(s));
}
public static boolean RegexQQ(String qq){
return qq!=null&&qq.matches("[1-9]\\d{5,19}");
}
public static boolean checkQQ(String qq) {
if (qq == null || qq.startsWith("0") || qq.length() < 6 || qq.length() > 20)
return false;
for (int i = 0; i < qq.length(); i++) {
char ch = qq.charAt(i);
if (ch < '0' || ch > '9')
return false;
}
return true;
}
}
String提供了一个匹配正则表达式的方法
public boolean matches(string regex)
判断字符串是否匹配正则表达式,匹配返回true,不匹配返回false。
email.matches(“\w{2,}@\w{2,20}(\.\w{2,10}){1,2”))
System.out.println(s2.replaceAll( regex “(.)\1+”,replacement: “$1”));
(.)一组:.匹配任意字符的。
\11:为这个组声明一个组号:1号
+声明必须是重复的字
$1
$1可以去取到第1组代表的那个重复的字
public class RegexTest6 {
public static void main(String[] args) {
String str="我我我喜欢欢欢欢欢编编编编程程程程程程程程程";
System.out.println(str.replaceAll("(.)\\1+","$1"));
}
}
四、异常
异常就是代表程序出现的问题。
- Error:代表的系统级别错误(属于严重问题),也就是说系统一旦出现问题,sun公司会把这些问题封装成Error对象给出来说白了,Error是给sun公司自己用的,不是给我们程序员用的,因此我们开发人员不用管它。
- Exception:叫异常,它代表的才是我们程序可能出现的问题,所以,我们程序员通常会用Exception以及它的孩子来封装程序出现的问题。
- 运行时异常:RuntimeException及其子类,编译阶段不会出现错误提醒,运行时出现的异常(如:数组索引越界异常)
- 编译时异常:编译阶段就会出现错误提醒的。(如:日期解析异常)
- 使用Ctrl alt T键选择try catch包围可能出现的异常程序段抛出异常
- 在方法后throws异常,表示将方法内的异常抛出。
自定义异常
Java无法为这个世界上全部的问题都提供异常类来代表,如果企业自己的某种问题,想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了
- 1、异常是用来查寻系统Bug的关键参考信息!
- 2、异常可以作为方法内部的一种特殊返回值,以便通知上层调用者底层的执行情况!
问题严重就自定义编译时异常,问题不严重就运行时异常。
public class RegexTest6 {
public static void main(String[] args) {
try {
setAge1(160);
}catch (Exception e){
e.printStackTrace();
}
}
public static void setAge(int age){
if(age>0&&age<150){
System.out.println("successful");
}else {
//用一个异常对象封装这个问题,throw抛出去这个异常对象
throw new AgeIllegalRuntimeException("/age is illegal, your age is"+age);
}
}
public static void setAge1(int age) throws AgeIllegalException {
if(age>0&&age<150){
System.out.println("successful");
}else {
//用一个异常对象封装这个问题,throw抛出去这个异常对象
throw new AgeIllegalException("/age is illegal, your age is"+age);
}
}
}
异常的处理
开发中对于异常的常见处理方式
可以都写Exception优化写法的
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionTest3 {
public static void main(String[] args) {
try {
test1();
} catch (ParseException e) {
e.printStackTrace();// 打印出这个异常对象的信息。记录下来。
} catch (FileNotFoundException e) {
e.printStackTrace();// 打印出这个异常对象的信息。记录下来。
}finally {
System.out.println("异常处理完毕");
}
}
public static void test1() throws ParseException, FileNotFoundException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d=simpleDateFormat.parse("2024-1-2 12:21:13");
System.out.println(d);
test2();
}
public static void test2() throws FileNotFoundException {
InputStream is=new FileInputStream("D:/meinv.jpg");
}
}
import java.util.Scanner;
public class ExceptionTest4 {
public static void main(String[] args) {
//尝试修复
while (true) {
try {
System.out.println(getMoney());
break;
} catch (Exception e) {
System.out.println("请您输入合法的数字!");
}
}
}
public static double getMoney(){
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入价钱!");
double v = scanner.nextDouble();
if(v>0) {
return v;
}
System.out.println("您输入的不合格!");
}
}
}