学习javaDay19

Day19

课程内容
	1、Lambda表达式
	2、函数式接口
	3、内置型函数式接口
	4、Stream的使用

一、Lambda表达式

1、本质:就是对接口匿名内部类的一种简写格式
2、前提:接口,必须是函数式接口(只有一个抽象方法)
3、表示就是一个接口的实现类对象

格式详解

1、格式:
	(参数列表) —>{方法体};
2、说明:
	(1)(参数列表)
		表示要实现的接口中,抽象方法的参数
	(2)->
		箭头运算符,lambda运算符,就是分隔前后两部分内容的
	(3)方法体:(lambda体)
		对抽象方法的具体实现
3、语法格式1:没有参数,没有返回值
       ()—> {方法体};
       简写格式,如果lambda中只有一条语句,可是省略大括号
   语法格式2:有一个参数,没有返回值
       (int x)->{方法体};
       如果只有一个参数,小括号是可以省略的,而且参数的类型的声明也是可以省略的
       x-> {方法体};
   语法格式3:有多个参数,有返回值
   		(x,y)->{方法体};
   		简写格式:如果只有return这一条语句,就可以省略大括号和return
   		eg:(x,y)->{return x + y;} 等价于 (x,y) -> x + y;

public class Demo_1 {
	public static void main(String[] args) {
//		lambda表达式
//		匿名内部类实现
		Inter_3 i3 = new Inter_3() {
			
			@Override
			public int test(int x, int y) {
				int sum = x + y;
				return sum;
			}
		};
		int test = i3.test(4, 9);
		System.out.println(test);
//		lambda表达式实现
		/*Inter_3 i33 =(x,y) -> {
			int sum = x + y;
			return sum;
		};
		int test2 = i33.test(98, 100);
		System.out.println(test2);*/
		
//		简写格式:如果只有return这一条语句,就可以省略大括号和return
		Inter_3 i33 =(x,y) -> x + y;
		int test2 = i33.test(98, 100);
		System.out.println(test2);
		
	}

	private static void test_2() {
		// 匿名内部类
		Inter_2 i2 = new Inter_2() {

			@Override
			public void test(int x) {
				System.out.println(x);
			}
		};
		i2.test(100);
//		lambda表达式实现
		/*Inter_2 i22 = (int x) -> {
			System.out.println(x + "lambda实现");
		};
		i22.test(999);*/
//		简写格式:如果只有一个参数,小括号是可以省略的,而且参数的类型的声明也是可以省略的
		Inter_2 i22 = m -> System.out.println(m + "lambda实现");

		i22.test(999);
	}

	private static void inter_1() {
		// 匿名内部类
		Inter_1 i1 = new Inter_1() {
			@Override
			public void test() {
				System.out.println("test方法");
			}
		};
		i1.test();

		// lambda表达式实现
		/*Inter_1 i2 = () -> {
			System.out.println("lambda实现的方法");
		};*/
		// 语法格式1,简写格式,如果lambda中只有一条语句,可是省略大括号
		Inter_1 i2 = () -> System.out.println("lambda实现的方法");

		i2.test();
	}
}

//接口必须是函数式接口
//没有参数,没有返回值g
interface Inter_1 {
	void test();
}

//有一个参数,没有返回值
interface Inter_2 {
	void test(int x);
}

//有多个参数,有返回值
interface Inter_3 {
	int test(int x, int y);
}

二、函数式接口

1、lambda前提就是函数式接口
2、定义:
	在一个接口中,只要一个抽象方法,那么这个接口就是函数式接口
3、检查
	@FunctionalInterface
	可以使用该注解完成对函数式接口的检查
	如果不是函数式接口,编译报错
4、理解:
	(1)函数:想表达的是一个方法的内容,由于方法不在任何类中,称为函数
	(2)函数式接口:想要表达的是方法,不再是接口
5、使用原因
	java语言,不支持将方法的实现逻辑作为一个参数进行传递
	解决:只能在方法的外面加上一层接口的声明,将来表面上传递方法所在接口的实现类对象,实际上是想间接的传递方法的实现逻辑。


public class Demo_2 {
	public static void main(String[] args) {
//		函数式接口
		FunInter_1 f1 = new FunInter_1() {
			
			@Override
			public void show() {
				System.out.println("show方法");
			}
		};
		FunInter_1 f2 = ()->System.out.println("lambda实现的方法");
		test(f2);
	}
	
	public static void test(FunInter_1 f1) {//传递方法的实现逻辑
		f1.show();
	}
	
}
@FunctionalInterface
interface FunInter_1{//在方法的外面套上了一层接口
	void show();
}

三、常用的内置型函数式接口

1、内置型函数型接口
	java8中提供了一些常用的内置型函数式接口,在使用类似功能的时候,就不需要额外定义接口,直接使用jdk中提供的即可
2、罗列:
	Consumer<T>:  消费型接口
		void accept(T t);
	Supplier<T>:  供给型接口
		T get();
	Function<T,R>:函数型接口
		R apply(T t);
	Predicate<T>: 断言型接口
		boolean test(T t);

消费型接口

1、Consumer<T>:  消费型接口
2、void accept(T t)
3、作用
	将来需要接受一个数据,并进行处理,处理之后,不需要返回数据,这个时候就可以使用消费型接口
	之前只能传递要处理的数据,现在可以传递处理数据的逻辑(方式,方法)


import java.util.function.Consumer;

public class Demo_3 {
//	消费型接口
	public static void main(String[] args) {
//		test("java"); 只能传递要处理的数据
		Consumer<String> con = x -> {//处理的逻辑,截取从2索引开始字符串
			String substring = x.substring(2);
			System.out.println(substring);
		};
		
		
		Consumer<String> con1 = x -> {//处理的逻辑,
			int length = x.length();
			System.out.println(length);
		};
		test(con1, "java");
	}
	
	public static void test(Consumer<String> con,String str) {
		con.accept(str);
	}
	
	public static void test(String str) {
		int length = str.length();
		System.out.println(length);
	}
}

方法引用

1、写一个函数式接口的时候,方法的实现,已经被某个其他的对象实现了,就不需要在lambada体中,再次实现这个方法,可以直接使用其他对象中已经定义好的方法
2、格式:
	函数式接口 名称 = 对象名 :: 方法名;
	函数式接口 名称 = 类名:: 静态方法名;
3、作用
	把已经实现的方法,作为一个数据,作为实现类对象,赋值给函数式接口的引用
	可以把这个引用当做方法的返回值,也可以作为方法的参数来进行传递。
4、本质:可以将任意的一个方法,作为函数式接口的一个实现类对象


import java.util.function.Consumer;

public class Demo_4 {
	public static void main(String[] args) {
//		方法引用
		Test test = new Test();
		test.show("长沙是个好地方");
	
//		Consumer<String> con = x -> System.out.println(x);
//		con.accept("长沙怎么老下雨");
//		accept(T t)一个参数,没有返回值
//		Consumer<String> con = test :: show;
		Consumer<String> con = System.out :: println;
		con.accept("长沙怎么老下雨");
		
		test(test::show);
//		
	}
	
	public static void test(Consumer<String> con) {
		con.accept("hello");
		
	}
}

class Test{
	public void show(String str) {//一个参数,没有返回值
		System.out.println(str);
	}
}

供给型接口

1、Supplier<T>
2、名称:供给型接口
3、抽象方法: T get()
4、作用:	
	需要定义一个方法,没有参数,但是可以产出一些数据,就可以使用供给型接口
	可以传递生产数据的方式


import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;

public class Demo_5 {
	public static void main(String[] args) {
//		供给型接口
//		List<Integer> num = getNum();
//		在调用方法的时候,传入生产数据的方式
		Supplier<Integer> sup = () -> {//   生产数据的逻辑
			Random random = new Random();
			return random.nextInt(20) + 1;
		};
		
		List<Integer> num = getNum(sup);
		System.out.println(num);
	}

	public static List<Integer> getNum(Supplier<Integer> sup) {
		List<Integer> list = new ArrayList<>();
		for (int i = 0; i < 10; i++) {
			list.add(sup.get());// 这里是不知道要添加什么样的数据
		}
		return list;
	}

	public static List<Integer> getNum() {
		List<Integer> list = new ArrayList<>();
		for (int i = 0; i < 10; i++) {
			list.add(i);
		}
		return list;
	}
}

函数型接口

1、Function<T,R>
2、R apply(T t)
3、作用
	将来需要将一个数据进行处理,并返回处理后的结果,就可以使用函数型接口
	以前我们传入要处理的数据,现在可以传入处理该数据的逻辑,方法,方式
4、方法:
	andThen(Funciton f)先对要处理的数据按照调用者函数型接口对象的中的逻辑进行处理,将处理后的结果作为参数函数型接口f中的参数,进行第二次处理,将结果返回


import java.util.function.Function;

public class Demo_6 {
	public static void main(String[] args) {
//		函数型接口
//		处理数据的逻辑
		/*Function<String, String> fun = m -> {
			String substring = m.substring(2);
			return substring;
		};
		funcitionInter(fun, "java");*/
		Function<String, String> fun1 = x -> x.toUpperCase();
		Function<String, Integer> fun2 = m -> m.length();
		funcitionInter(fun1, fun2, "hello");

	}

//	andThen方法
	public static void funcitionInter(Function<String, String> fun1, Function<String, Integer> fun2, String str) {
//		String strsString = fun1.apply(str);// 先将str按照fun1指定的逻辑进行处理
//		Integer apply = fun2.apply(strsString);
//		
//		System.out.println("一次处理后的结果" + strsString);
//		System.out.println("二次处理后的结果" + apply);
		
		Integer apply = fun1.andThen(fun2).apply(str);//先对str按照fun1中的逻辑
        进行处理,将处理后的结果作为fun2的参数,进行第二次处理,将结果返回
		System.out.println(apply);
        
	}

//	Function<String, Integer> fun  处理str的逻辑,String str要处理的字符串
	public static void funcitionInter(Function<String, String> fun, String str) {
		String strsString = fun.apply(str);// 使用fun完成了对str的处理,但是不知道是怎么样去处理str这个数据
		System.out.println(strsString);
	}

	public static int swtichData(String str) {
		return str.length();// String 数据传入方法,得到一个int类型数据
	}
}

断言型接口

1、Predicate<T> 断言型接口
2、boolean test(T t)
3、作用:
	需要定义一个函数,接口一个数据,并对该数据进行判断,判断该数据是否满足指定的条件,返回一个boolean类型的值,就可以是断言型接口
	以前只能传入要判断的数据,现在可以传入对数据的判断逻辑
4、方法
	and(Predicate<T> pre) 在调用者条件判断之后,再由参数条件进行判断,最后返回同时满足两个条件的结果
	or(Predicate<T> pre) 在调用者条件判断之后,再由参数条件进行判断,最后返回满足任意一个条件的结果
	negate(Predicate<T> pre) 调用者条件判断取反


import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class Demo_7 {
	public static void main(String[] args) {
//		断言型接口
		List<String> list = new ArrayList<String>();
		list.add("张飞");
		list.add("张三");
		list.add("张伟");
		list.add("张益达");
		list.add("诸葛亮");
		list.add("司马相如");
		list.add("上官婉儿");
		
//		List<String> newList = filterList(list);
//		System.out.println(newList);
		Predicate<String> pre = m -> m.startsWith("张");
		Predicate<String> pre1 = m -> m.length() == 4;
		List<String> filterList = filterList(list,pre1);//传入判断数据的逻辑
		System.out.println(filterList);
//		---------------and-----------------
		/*	Predicate<String> pre1 = m -> m.startsWith("张");
			Predicate<String> pre2 = m -> m.length() == 4;
			List<String> filterList = filterList(list,pre1,pre2);
			System.out.println(filterList);*/
	}
//	and or
	
	public static List<String> filterList(List<String> list,Predicate<String> pre1,Predicate<String> pre2){
		List<String> newList = new ArrayList<String>();
		for (String string : list) {
//			if(pre1.test(string) && pre2.test(string)) {
//			if(pre1.and(pre2).test(string)) {//和上面实现的效果是等价的
			if(pre1.or(pre2).test(string)) {
				newList.add(string);
			}
		}
		return newList;
	}
//	negate
	public static List<String> filterList(List<String> list,Predicate<String> pre){
		List<String> newList = new ArrayList<String>();
		for (String string : list) {
//			if(!pre.test(string)) {
			if(pre.negate().test(string)) {
				newList.add(string);
			}
		}
		return newList;
	}
	
//	 对list集合中的数据进行筛选,只要姓张的
	public static List<String> filterList(List<String> list) {
		List<String> newList = new ArrayList<String>();
		for (String string : list) {
			if(string.startsWith("张")) {
				newList.add(string);
			}
		}
		return newList;
	}
}

四、Stream(流)

1、在java8中,提供了一个Stream类型
2、作用:
	可以快速完成对数据的过滤(筛选)

Stream类型数据的获取

1、Collection的获取
	调用Stream()方法,返回Stream类型的对象
2、Map集合
	(1)keySet方法,Set<Key> 再去调用stream()方法
	(2)entrySet方法,Set<Key,Value>再去调用stream()方法
	(3)values方法,Collection<Value>再去调用stream()方法
3、数组的获取
	Stream.of(数组)



import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Stream;

public class Demo_8 {
//Stream流的获取
	public static void main(String[] args) {
//		Collection set,list,ArrayList,LinkedList,HashSet
		HashSet<String> hs = new HashSet<>();
		Stream<String> s = hs.stream();
//		Map
		HashMap<String, Integer> hm = new HashMap<String, Integer>();
		Set<String> keySet = hm.keySet();
		Stream<String> stream = keySet.stream();
		
		Set<Entry<String, Integer>> entrySet = hm.entrySet();
		Stream<Entry<String, Integer>> stream2 = entrySet.stream();
		
		Collection<Integer> values = hm.values();
		Stream<Integer> ssStream = values.stream();
//		数组,数组获取Strema类型的方式
		Integer[] arr = {1,2,3,2,32,32,32,32,3};
		Stream<Integer> of = Stream.of(arr);
	}
}

Stream中的常用方法

1、大多数方法都是对流中的数据,进行过滤或者筛选的。
2、分类:
	终结方法:调用完之后,返回值不再是Stream类型了,无法继续使用Stream中的方法
		eg:forEach,count
	延迟方法:调用完之后,返回值还是Stream类型了,可以继续使用Stream中的方法
		eg:skip,limit,map,filter
3、常用的方法
 Stream	filter(Predicate<T> pre)
		根据pre描述的条件,对流中的数据进行过滤
 void forEach(Predicate<T> pre)
		将流中的数据,根据con指定的数据处理方式,进行处理
 Stream limit(long n);
 		根据参数n描述的个数,对流中的数据进行截取
 Stream skip(long n) 
 		跳过参数n所描述元素的个数,流中剩余的是n之后的内容
 long count();
 		返回流中元素的个数。
 Stream  map(Function<T, R> fun) 
 		将流中所有T类型的数据,根据fun指定的处理逻辑,转换成R类型的数据
 static Stream  concat(Stream steam1,Stream stream2)
 		将流stream1和stream2两个流中的数据合并到一个流中


import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class Demo_9 {
	public static void main(String[] args) {
//		Stream的常用方法
		List<String> list = new ArrayList<String>();
		list.add("许仙");
		list.add("青儿");
		list.add("法海");
		list.add("白素贞");
		list.add("许三多");
		list.add("许文强");
//		获取一下该集合的Stream流
		Stream<String> stream1 = list.stream();
//		filter(Predicate<T> pre)
		Predicate<String> pre = x -> x.length() == 2;
		Stream<String> stream2 = stream1.filter(pre).filter(x -> x.startsWith("许"));
//		forEach(Consumer<T> t) 将流中的数据,根据con指定的数据处理方式,进行处理
//		Consumer<String> con = x->System.out.println(x);
//		filter.forEach(x->System.out.println(x));
		stream2.forEach(System.out::println);//一旦Stream对象调用了终结方法eg:foreach就不能再使用了
//		stream2.filter(x->x.length()==4);
//		--------limit----------------------
		System.out.println("--------limit----------------------");
		Stream<String> limitStream1 = list.stream();
		limitStream1.limit(3).forEach(System.out::println);
//		--------skip----------------------
		System.out.println("--------skip----------------------");
		Stream<String> limitskip = list.stream();
		limitskip.skip(3).forEach(System.out::println);
//		--------count----------------------
		System.out.println("--------count----------------------");
		Stream<String> limitcount = list.stream();
		long count = limitcount.skip(3).count();
		System.out.println(count);
//		--------map----------------------
//		map(Function<T, R> fun) 将流中所有T类型的数据,根据fun指定的处理逻辑,转换成R类型的数据
		System.out.println("--------map----------------------");
		Stream<String> mapStream = list.stream();
		Function<String,  Person> fun = m -> new Person(m);
		mapStream.map(fun).forEach(System.out::println);
//		Function<String,  Integer> fun = x-> x.length();
//		mapStream.map(fun).forEach(System.out::println);;
//		--------concat----------------合并两个流对象
		System.out.println("--------concat--静态方法--------------------");
//		要求:要合并的两个流对象不能调用终结方法的
		Stream<String> conStream1 = list.stream();
		Stream<String> filter1 = conStream1.filter( x->x.length() == 2 );
		
		Stream<String> conStream2 = list.stream();
		Stream<String> filter2 = conStream2.filter(x->x.startsWith("白"));
//		合并两个流
		Stream<String> concat = Stream.concat(filter1, filter2);
		concat.forEach(System.out::println);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值