jdk1.8新特性-利用已有java基础知识学未学知识-个人学习笔记

本文介绍了Java 1.8中接口的改变,包括默认方法和静态方法的引入,以及Lambda表达式的使用。Lambda允许更简洁地实现接口,它由箭头操作符分割参数列表和方法体。文中通过示例展示了如何使用Lambda实现接口方法,以及方法引用的运用。此外,还探讨了Stream API,包括创建Stream、中间操作和终端操作,展示了如何在实际问题中应用Stream进行数据处理。
摘要由CSDN通过智能技术生成

在此之前要先了解一下接口咋JDK1.8前后变化,接口不了解,源码都没法看。

1 基础-接口篇

1.1 JDK1.8之前

官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

简单理解:接口里面全部是由全局常量和公共的抽象方法所组成。(JDK1.8之前可以这样理解)

一个简单的接口例子

//Java类型名通常以大写字母开头
interface In1{
    //全局常量
    final int a = 10;
    //抽象方法
    void display();
}

有兴趣还可以去了解一下注解(注解本质还是一个接口),特别是注解接口。

1.2 JDK1.8之后

JDK1.8,接口中的方法可以有方法体(1.8之前没有的)但需要关键字static或者default来修饰,使用static来修饰的称之为静态方法,静态方法通过接口名来调用,使用default来修饰的称之为默认方法,默认方法通过实例对象来调用

例子:

interface In1{
    //全局常量
    final int a = 10;
    //抽象方法
    void display();
    //jdk1.8之后,可以有方法体,用static修饰
    static void display(){
        System.out.println("a="+a);
    }
    //jdk1.8之后,可以有方法体,用default修饰
    default void display(){
        System.out.println("2a="+2*a);
    }
}
public class In1Impl implements In1{
	@Override
	public void display() {
		// TODO 自动生成的方法存根
		System.out.println("我是jdk1.8之前的");
	}
}
public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		In1Impl In1Impl1 = new In1Impl();
		In1Impl1.display();//JDK1.8之前,通过实例对象来调用
		In1Impl1.display2();//default通过实例对象来调用
		In1.display1();//static通过接口名来调用
	}
}

2 特性1-Lambda表达式

了解完接口的变化后,对lambda表达式也更容易去学习lambda表达式本质上是一段匿名内部类,使用lambda表达式可以对一个接口进行非常简洁的实现,而且接口定义的必须要实现的抽象方法只能有一个。这里就不拿匿名函数做比较了,拿接口做比较方便。

Lambda表达式在Java语言中引入了一个操作符**“->”**,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:

  • 左侧:指定了Lambda表达式需要的所有参数,用( )来描述参数列表,参数一个可以省略()。
  • 右侧:制定了Lambda体,即Lambda表达式要执行的功能,用{ }来描述方法体,方法体只有一条语句可以省略。

具体的语法实例就不说了,给大家主动去回想,加强记忆,没接触过就给大家刘个举一反三的空间,加强学习效果。

2.1 通过接口实现

一个简单例子(不用lambda表达式,不用匿名函数)

public class Test2 {
	public static void main(String[] args) {
		Comparator.compare(10, 5);
	}
}
//比较a和b的大小
interface Comparator{
	static void compare(int a,int b) {
		if(a-b>0) System.out.println("a>b");
		else System.out.println("a<b");
	}
}

对比观察,使用lambda表达式

public class Test2 {
	public static void main(String[] args) {
		Comparator2 comparator2 = (a, b) -> {
			if(a-b>0) System.out.println("a>b");
			else System.out.println("a<b");
		};
		comparator2.compare(10, 5);
	}
}

interface Comparator2{
	void compare(int a,int b);
}

2.2 lambda方法引用

普通方法的引用

public class Test2 {
	public static void main(String[] args) {
		//方法引用:快速的将一个Lambda表达式的实现指向一个已经实现的方法
		Comparator2 comparator2 = (a, b) -> compare(a,b);
		comparator2.compare(10, 5);
		//和上面等同,用方法的隶属者::方法名
        //静态方法中,隶属者是类,非静态,隶属者是一个对象实例
		Comparator2 comparator2_2 = Test2::compare ;
		comparator2_2.compare(10, 5);
	}
    //静态方法
    private static void compare(int a,int b){
        if(a-b>0) System.out.println("a>b");
		else System.out.println("a<b");
    }
}

interface Comparator2{
	void compare(int a,int b);
}

构造方法的引用

//实体类
public class Person {
	String name;
	private int age;

	public Person() {
		System.out.println("无参构造方法已经执行");
	}
	
	public Person(String name, int age) {
		this.name=name;
		this.setAge(age);
		System.out.println("有参构造方法已经执行");
	}
	
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
public class test4 {
	public static void main(String[] args) {
		GetPersion create = () -> new Person();
		//修改成构造方法的引用
		GetPersion create1 = Person::new;
		Person a = create1.getPerson();
		
		//修改成构造方法的引用
		GetPersion2 create2 = Person::new;
		Person b = create2.getPerson("Lq林", 10);
	}
}

interface GetPersion{
	Person getPerson();
}

interface GetPersion2{
	Person getPerson(String name, int age);
}

2.3 lambda常用实例

排序:

public class Test5 {

	public static void main(String[] args) {
		ArrayList<Person> list = new ArrayList<>();
		
		list.add(new Person("a",10));
		list.add(new Person("b",15));
		list.add(new Person("c",13));
		list.add(new Person("d",20));
		list.add(new Person("e",11));
		
		//排序,开发工具中选择查看sort声明可见sort方法,对应下文的int compare(T o1, T o2);
		list.sort((o1, o2) -> o2.getAge() - o1.getAge());
		System.out.println(list);
	}

}
//补充介绍说明sort方法,该方法是ArrayList包下的方法
@Override
    @SuppressWarnings("unchecked")
    //
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

//补充说明Comparator
@FunctionalInterface//lambda的专门的函数式接口
public interface Comparator<T> {
...
    int compare(T o1, T o2);
...
}

循环forEach

public class Test6 {

	public static void main(String[] args) {
		//集合遍历
		ArrayList<Integer> list = new ArrayList<>();
		//添加元素
		Collections.addAll(list, 1,2,3,4,5,6,7,8,9,0);
		//集合遍历有遍历下标,for循环,迭代器和forEach实现,这里用forEach实现
		//将集合中的没一个元素都带入方法accept中。
		list.forEach(System.out::println);
		//遍历偶数
		list.forEach(ele ->{
			if (ele % 2 == 0) System.out.println(ele);
		});
	}

}

其他的基础实例有增加和删除,线程实例等等,在此省略,常用接口JDK1.8都内置好了。

2.4 lambda的函数式接口

函数式接口:有且仅有一个抽象方法的接口。这主要体现在lambda(其他新特性在源码中也有体现)中。直接给接口添加@FunctionalInterface 注解就OK了,编译器发现该接口多于一个抽象方法就会报错。

3 特性2-Stream

Stream:流,数据渠道,操作(如筛选、排序等)数据源(集合数组等)产生的元素序列。对stream的流水线式操作分为两类,中间操作和结束操作。中间操作形成一条流的流水线,不生成结果,不执行操作;结束操作执行流水线全部内容(包括中间操作的内容),并能生成结果。

3.1 创建Stream的几种方式

数组arrays,集合list,stream中的静态方法of()、重复iterate和空empty等。

其中创建Stream有顺序流和并行流;如果流中的数据量足够大,并行流可以加快处速度

注:直接创建并行流,还可以通过parallel()把顺序流转换成并行流。

public class Stream1 {
/**
 * 1.创建Stream,有stream()顺序流和parallelStream()并行流,此处只用顺序流
 * 2.中间操作
 * 3.终止操作
 * @param args
 */
	public static void main(String[] args) {
	    // 1、数组,通过Array
	    String[] arr = new String[]{"ab", "cd", "ef"};
	    Stream<String> Stream1 = Arrays.stream(arr);
	    
	    // 2、集合,通过list
	    List<String> list = Arrays.asList("ab", "cd", "ef");
	    Stream<String> Stream2 = list.stream();
	    
	    // 3.1、值,通过stream中的静态方法of()
	    Stream<String> stream3 = Stream.of("ab", "cd", "ef");
	    
	    // 3.2、迭代,通过stream中的静态方法iterate创建无限流,0是初始元素,打开iterate声明翻译可知
	    Stream<Integer> stream4 = Stream.iterate(0,(x) -> x+2);
	    
        //对4进行中间操作和终止操作
	    stream4.limit(10).forEach(System.out::println);
	}
}

3.2 stream的中间操作

筛选和切片、映射、排序、查找与匹配等

例如筛选与切片的:

方法描述
filter(Predicate p)过滤,接收Lambda表达式,从流中排除某些元素
distinct()大多人理解成:筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素(本人个人理解:关键词 DISTINCT 用于返回唯一不同的值
limit(long maxSize)截断流,使其元素不超过给定数量(本人理解:关键词limit用于限制数量maxSize)
skip(long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补

上文中,这条语句的中间操作就是limit。

//对4进行中间操作和终止操作
stream4.limit(10).forEach(System.out::println);

更多中间操作实例可参考

大佬冰河【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!

3.3 终止stream的几种方式

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如: List、 Integer、Double、String等等,甚至是 void 。

拿最简单的查找与匹配有关的

tream API中有关查找与匹配的方法如下表所示。

方法描述
allMatch(Predicate p)检查是否匹配所有元素
anyMatch(Predicate p)检查是否至少匹配一个元素
noneMatch(Predicate p)检查是否没有匹配所有元素
findFirst()返回第一个元素
findAny()返回当前流中的任意元素
count()返回流中元素总数
max(Comparator c)返回流中最大值
min(Comparator c)返回流中最小值
forEach(Consumer c)内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)

例子:还是拿回上文最熟悉的那个forEach内部迭代

//对4进行中间操作和终止操作
stream4.limit(10).forEach(System.out::println);

更多终止操作实例可参考

大佬冰河

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LQ小林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值