java基础之lambda表达式

                            java基础之lambda表达式

1 什么是lambda表达式

lambda表达式是一个匿名函数,允许将一个函数作为另外一个函数的参数,将函数作为参数传递(可理解为一段传递的代码)。

2 为什么要用lambda表达式

lambda表达式可以写出更简洁更灵活的代码。先看看下面一段代码

public class TestLambda {
	//匿名内部类方式
	@Test
	public void test() {
		TreeSet<Integer> set = new TreeSet<>(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {			
				return Integer.compare(o1, o2);
			}		
		});
	}
	//lambda方式
	@Test
	public void test1() {
		Comparator<Integer> com = (x,y)->Integer.compare(x, y);
		TreeSet<Integer> set = new TreeSet<>(com);		
	}
    List<Person> list = Arrays.asList(new Person("小红", 18, 5000.0), new Person("小明", 21, 6000.0),new Person("小刚", 25, 7000.0));

	// 传统方式获取年龄大于20的人
	@Test
	public void test2() {
		for (Person person : list) {
			if(person.getAge()>20) {
				System.out.println(person);
			}
		}
	}

	// lambda方式获取年龄大于20的人
	@Test
	public void test3() {
		list.stream()
		.filter((x)-> x.getAge()>20)
		.forEach(System.out::println);
	}
}

 

3 lambda语法

java8中引入了操作符“->”,称为箭头操作符或lambda操作符,lambda用于替换匿名函数。

使用lambda表达式的前提:接口(函数式接口)中只能有一个抽象方法。

函数式接口:接口中只有一个抽象方法的接口,通过注解@Functioninterface 限定

lambda操作符将lambda表达式拆成两个部分:

(1)左侧是lambda表达式的参数列表(可以理解为抽象方法的参数)

(2)右侧是lambda表达式中需要执行的功能,即lambda体(可以理解为抽象方法的实现的功能)

3.1 格式一:无参数,无返回值

()->System.out.println("Hello Lambda!");

3.2 格式二:有一个参数,无返回值(如果只有一个参数可以省略(),如果只有一条语法可以省略{})

(x)->System.out.println(x);

3.3 格式三:如果只有一个参数,小括号可以省略不写

x -> System.out.println(x);

3.4 格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句

Comparator<Integer> com = (x, y) -> {

          System.out.println("函数式接口");

           return Integer.compare(x, y);

};

3.5 格式五:如果 Lambda 体中只有一条语句, return 和 大括号都可以省略不写

Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

3.6 格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”

(Integer x, Integer y) -> Integer.compare(x, y);

 

4 内置的四个核心函数式接口

4.1 消费型接口Consumer<T>

抽象方法:void accept(T t);

    //消费型接口
	@Test
	public void test1() {
    //	Consumer<Double> con = (x)-> System.out.print(x);
   	//	consumer(100, con);
		consumer(100,(x)-> System.out.print(x));
	}
	public void consumer(double money,Consumer<Double> con){
		con.accept(money);
	}

4.2 供给型接口Supplier<T>

抽象方法:T get();

	//供给型接口
	@Test
	public void test2() {
		List<Integer> randomNum = getRandomNum(10,()->new Random().nextInt(100));
		System.out.println(randomNum);
	}
	/**
	 * @Description 生成指定个数的随机数
	 * @param count
	 * @param su
	 * @return int
	 */
	public List<Integer> getRandomNum(int count,Supplier<Integer> su) {
		List<Integer> list = new ArrayList<>();
		for(int i = 0;i<count;i++) {
			list.add(su.get());
		}
		return list;
		
	}

4.3 函数式接口Function<T,R>

抽象方法:R apply(T t);

	//函数式型接口
	@Test
	public void test3() {
	
		List<String> list = toUpperList(new ArrayList<String>(Arrays.asList("abc","df","aa","cc")),
				(x)-> x.toUpperCase()
				);
		System.out.println(list);
	}
	/**
	 * @Description 将集合里面的字符串转大写
	 * @param list
	 * @param fun
	 * @return List<String>
	 */
	public List<String> toUpperList(List<String> list,Function<String,String> fun){
		for(int i = 0;i < list.size();i++) {
			String apply = fun.apply(list.get(i));
			list.set(i, apply);
		}	
		return list;	
	}

4.4 断言型接口Predicate<T>

抽象方法:boolean test(T t);

//断言型接口
	@Test
	public void test4() {
		List<String> list = Remove(new ArrayList<String>(Arrays.asList("abc","df","aa","cc")),
				(s) -> s.length() < 2);
		System.out.println(list);
	}
	/**
	 * @Description 删除集合中长度小于2的元素
	 * @param list
	 * @param pre
	 * @return List<String>
	 */
	public List<String> Remove(List<String> list,Predicate<String> pre) {
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			String str = it.next();
			if(pre.test(str)) {
				list.remove(str);
			}
		}
		return list;
		
	}

5 方法引用

5.1 方法引用

将Lambda体中的功能,已有方法方法提供了实现,可以使用方法引用(方法引用可以理解为Lambda的另一种表现形式)

方法引用分类:

(1)对象的引用::实例方法名

    //对象的引用::实例方法名
	@Test
	public void test1() {
		Date date = new Date();
		//传统lambda表达式
		Supplier<Long> su = ()-> date.getTime();
		System.out.println(su.get());
		//对象引用
		Supplier<Long> su1 = date::getTime;
		System.out.println(su1.get());
	}

(2)类名::静态方法名

    //类名::静态方法名
	@Test
	public void test2() {
		Comparator<Integer> com = (x,y)-> Integer.compare(x, y);
		System.out.println(com.compare(4, 5));
		
		Comparator<Integer> com1 = Integer::compare;
		System.out.println(com1.compare(4, 5));
	}

(3)类名::实例方法名

    //类名::实例方法名
	@Test
	public void test3() {
		Function<Person,String> fun = (x)-> x.show();
		System.out.println(fun.apply(new Person()));
		
		Function<Person,String> fun1 = Person::show;
		System.out.println(fun.apply(new Person()));
	}
	class Person{
		public String show() {
			return "aaa";
		}
	}

注意:方法引用所引用的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致。若Lambda的参数列表的第一个参数,是实例方法的调用,第二个参数(或无参)是实例方法的参数是,格式:ClassName::MethodName

5.2 构造器引用

构造器中的参数列表需要与函数式中参数列表保持一致

类名::new 

    //类名 :: new
	@Test
	public void test4() {
		Supplier<Person> sup = () -> new Person();
		System.out.println(sup.get());
				
		Supplier<Person> sup2 = Person::new;
		System.out.println(sup2.get());
	}

 

6 Stream

6.1 什么是Stream

Stream流是数据管道,用于操作数据源(集合,数组)所产生的元素序列。

Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,需要对元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。Stream是单向的数据只能遍历一次。迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。

注意:①stream自己不会存储元素;②stream不会改变对象,他会返回一个新的stream;③stream的操作是延迟的。

6.2 Stream的操作

操作步骤:①创建Stream;②中间操作;③终止操作

(1)创建流

    @Test
	public void test1() {
		//1.Collection获取流,获取到的是顺序流
		List<String> list = new ArrayList<>();
		Stream<String> stream = list.stream();
		
		//2.通过Arrays中的stream获取一个数组流
		String[] arr = new String[5];
		Stream<String> stream2 = Arrays.stream(arr);
		
		//3.通过Stream类中的静态方法of
		Stream<Integer> of = Stream.of(11,22,33,44,55);
		
		//4.创建无限流
		Stream<Integer> limit = Stream.iterate(0, (x)-> x + 1).limit(20);
		limit.forEach(System.out::println);
		
		//5.用Stream的generate生成
		Stream<Double> limit2 = Stream.generate(Math::random).limit(20);
		limit2.forEach(System.out::println);
	}

(2)中间操作:

常用中间操作方法如下:

方法描述
Stream<T> filter(Predicate<? super T> predicate)接收Lambda,从流中排除某些元素
Stream<T> limit(long maxSize)截断流,使元素不超过给定数量
Stream<T> skip(long n) 

 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个流,与limit(n)互补

Stream<T> distinct()帅选通过流所生成元素的 hashCode() 和 equals() 去除重复元素
<R> Stream<R> map(Function<? super T,? extends R> mapper)

接收一个lambda,将元素转成成其他形式或提取信息,接收一个函数作为参数,该函数会被 应用到个元素上,并将其映射成一个新元素

(3)终止操作

常用终止操作如下

方法描述
boolean allMatch(Predicate<? super T> predicate)  

检查是否匹配所有元素

boolean anyMatch(Predicate<? super T> predicate)  

检查是否至少匹配一个元素

boolean noneMatch(Predicate<? super T> predicate)  

检查是否没有匹配的元素

Optional<T> findFirst()  

返回第一个元素

Optional<T> findAny()  

返回当前流中的任意元素

long count()

返回流中元素的总个数

Optional<T> max(Comparator<? super T> comparator)  

返回流中最大值

Optional<T> min(Comparator<? super T> comparator) 

返回流中最小值

案例:

@Test
	public void test2() {
		List<String> list = Arrays.asList("a","d","e","b","c");
		//自然排序
		list.stream()
		.sorted()
		.forEach(System.out::println);
		
		//定制排序
		List<Person> p = new ArrayList<>();
		p.add(new Person("aa",18,100.0));
		p.add(new Person("cc",16,150.0));
		p.add(new Person("bb",20,180.0));
		p.stream()
		.sorted((e1,e2)->{
			if(e1.getAge()==e2.getAge()) {
				return e1.getName().compareTo(e2.getName());
			}else {
				return e1.getAge()-e2.getAge();
			}
		}).forEach(System.out::println);
	}
	class Person {
		private String name;
		private int age;
		private double score;

		public Person() {

		}

		public Person(String name, int age, double score) {
			this.name = name;
			this.age = age;
			this.score = score;
		}
		

		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 double getScore() {
			return score;
		}

		public void setScore(double score) {
			this.score = score;
		}

		@Override
		public String toString() {
			return "Person1 [name=" + name + ", age=" + age + ", score=" + score + "]";
		}

	}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值