前面也有写一篇jdk8 + guava的博文,都是一些零碎的记录,感觉不是很好。
都说java8运行速度比之前的其他版本要快很多,这都要归功于Stream的概念,既然能那么快就从它与多线程的关系说起吧。
1、java 8 和多线程
在java8之前通过多线程来达到并行效果需要使用Thread API,syncharonized关键字,同时当线程访问并更新共享变量时,要是没有协调好线程之间的关系,可能就会出错。
而在java8中,会更多关注的是数据分块,而不是协调问题,所以基本上很少使用syncharonized,而是使用Stream的并行化方式来处理的。
如在两个CPU上刷选列表,可以先让一个CPU处理列表的前一半,另一个CPU处理后一半,即将大的数据流分块成小的数据流来处理,接着CPU会各自对自己的半个列表进行筛选,最后将两个结果合并到一个CPU上,在此基础上,当CPU越多,处理能力当然就会越强,既可以横向扩展。所以在处理时,基本上都会先将其转换成stream(parallelStream):
asList.stream().filter((String s) -> s.contains(“v")).collect(Collectors.toSet());
2、行为参数化
依旧使用上一个例子吧,行为参数化简单的来说就是把一个行为(即一段逻辑代码)封装起来,通过传递的方式将方法的行为参数化,即:上例中的(String s) -> s.contains(“v”)就表示一段行为,将其通过lambda方式作为参数传递至filter函数中,可以很大程度上简洁代码,且逻辑也很清晰。当lambda主体(即 -> 之后的内容)很多时,需要使用{}花括号将其包裹。
3、在java8中lambda当然是重点之一了
先看一下例子吧:
(Integer i) -> return “Study” + i;
(Strings) -> {“Study”;}
上面这两个其实都不是正确的lambda,第一个中必须使用花括号将这个控制流语句给包起来才可以,即(Integer i) ->{return “Study” + i};
至于第二个后面的部分是一个表达式,而不是语句,可以直接去掉花括号,或采用显式返回语句,即(Strings) -> {return “Study”;}
4、函数式接口
即只定义了一个抽象方法的接口(并不是之后一个方法,还可以有其他默认方法,或静态方法,仅仅是抽象方法只有一个而已)。java8中会大量的用到此接口,并且你可以看到一般像这种接口都会使用@FunctionalInterface来注解,简单的介绍几个最常用的吧:
1)java.util.function.Predicate<T>
它包含一个boolean test(T t);抽象方法,所以一般是在需要处理boolean问题时使用它:
stream.filter(vo -> vo.getAge()>25).distinct().skip(3).limit(6).collect(Collectors.toList());
2)java.util.function.Consumer<T>
void accept(T t); 即对给定的参数T执行操作,最常用的莫过于forEach了:
asList.forEach(System.out::print);
3)java.util.function.Function<T, R>
R apply(T t); 接受一个参数T,还需要返回一个类型R,所以一般为将某一个对象的信息映射输出。
str.chars().mapToObj(ch -> Character.valueOf((char)ch)).forEach(System.out::print);
函数式接口 | 函数描述符 | 原始类型特化 |
Predicate<T> | T -> boolean | IntPredicate, LongPredicate, DoublePredicate |
Consumer<T> | T -> void | IntConsumer, LongConsumer, DoubleConsumer |
Fuction<T,R> | T -> R |
IntFunction<R>, IntToDoubleFunction, IntToLongDouble
LongFunction<R>, LongToDoubleFunction, LongToIntFunction,
DoubleFunction<R>
ToIntFunction<T>, ToDoubleFunction<T>, ToLongFunction<T> |
Suppliter<T> | () -> T |
BooleanSupplier, IntSupplier, LongSuppliter, DoubleSuppliter |
UnaryOperator<T> | T -> T |
IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator |
BinaryOperator<T> | (T, T) -> T |
IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator |
BiPredicate<L, R> | (L, R) -> boolean | |
BiConsumer<T, U> | (T, U) -> void |
ObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T> |
BiFunction<T, U, R> | (T, U) -> R |
ToIntBiFunction<T, U>, ToLongBiFunction<T, U>, ToDoubleBiFunction<T, U> |
5、在java8中,因为泛型只能绑定到引用类型,所以就会存在一个装箱 和 拆箱的问题:
装箱:将原始类型转换为引用类型(int -> Integer)。
拆箱:将引用类型转换为原始类型(Integer -> int)。
虽然有提供自动装箱过程,但由于装箱之后的存储值会需要更多的内存,且在搜索时也需要更多的内存来获取被包裹的原始值,在性能方面会消耗,所以提供了原始类型前缀的接口DoublePredicate、IntConsumer、LongBinaryOperator、IntFunction、ToIntFunction、IntToFunction等。
6、lambda与局部变量
要在lambda中使用局部变量,需要为变量添加final修饰符,guava中也存在。
对于局部变量的限制是因为:实例变量存储在队中,而局部变量存在在栈中,如果lambda可以直接访问局部变量,而lambda又在线程中使用,则会使用到lambda的线程,可能会在分配该变量的线程将这个变量收回之后才去访问该变量。因此当java访问自由局部变量时,实际上访问的是它的副本,而不是原始值。
7、lambda匿名类与闭包
所谓闭包,也就是一个函数的实例,只是可以将这个实例作为参数传递给另一个函数,并可以无限制的访问和修改其作用域之外的变量。而lambda虽然也可以作为参数传递给另一个函数,但它不能修改定义lambda的方法的局部变量,它和闭包还是有区别的。
8、lambda与方法引用,即使用::方式直接调用对应的方法
lambda中的方法引用也用的蛮多的,如下Math::random即Math.random()函数的引用:
Stream.generate(Math::random).limit(5);
构造函数的引用:
//无参构造函数
Supplier<UserVO> su = UserVO::new;
UserVO vo01 = su.get();
//一个参数的构造函数
Function<String, UserVO> fun = UserVO::new;
UserVO vo02 = fun.apply("xiaomi");
//两个参数的构造函数
BiFunction<String, Integer, UserVO> bifun = UserVO::new;
UserVO vo03 = bifun.apply("xiaomi", 4);
//多个参数的构造函数需要自己去自定义了
DataFunction<String, String, String, String, Record> data = Record::new;
Record record = data.apply("title", "content.....", "https://www.xiaomi.com", "search");
相关推荐
Java 记录随笔 Java 记录随笔是关于 Java 软件架构设计的笔记,涵盖了软件架构的基本原则、当前流行的技术、数据库存储结构、Web 界面用户接口层、业务层架构、持久层技术、XML 结构化信息传输和存储的重要性等多个...
在本文中,我们将深入探讨如何在Ubuntu操作系统上搭建一个完整的Java项目运行环境,包括安装Java Development Kit (JDK) 1.8、MySQL 5.7数据库服务以及Apache Tomcat 9应用服务器。这个过程对于任何希望在Linux环境...
每四位二进制数对应一个十进制数,如二进制的1101代表十进制的13,因为1*8 + 1*4 + 0*2 + 1*1 = 8 + 4 + 0 + 1 = 13。8421码在某些特定的数字处理场景中很有用,如电子表格软件或计算器。 Java中的位运算,如与(&)...
在Java世界,Map对象转换为实体类通常是通过ORM框架如MyBatis Plus完成的,而实体类转化为JSON则可以借助Jackson或Gson库。例如,使用Gson库,可以写成`Gson gson = new Gson(); String jsonString = gson.toJson...
Java基于SWT(Standard Widget Toolkit)开发的记事本程序是一种桌面应用程序,它提供了与操作系统原生记事本相似的功能和用户体验。SWT是Eclipse基金会维护的一个开源库,用于构建Java GUI应用,其特点在于能够更...
标题“2014210-2014307笔记随笔”暗示了这是一份时间跨度从2014年2月10日至3月7日的个人学习记录,可能包含了作者在IT领域的所学所悟,特别是关于编程、软件开发或系统设计的思考。由于描述部分为空,我们无法直接...
在开发“Android App_云随笔课程设计”项目时,我们面临的是构建一个移动应用程序,旨在帮助用户便捷地记录他们的日常生活、旅行体验、心情点滴以及学习笔记等。这个应用程序的关键特性在于其同步功能,它将用户的...
【DCSweb随笔】是一篇关于分布式控制系统(DCS,Distributed Control System)与相关工具的文章,结合了源码分析和技术实践。虽然具体的博文内容没有直接提供,但我们可以从标题和标签中推测讨论的主题可能涉及到DCS...
Ibatis 是一款轻量级的Java持久层框架,它的核心思想是将SQL语句与Java代码分离,使得开发者可以更加灵活地控制SQL的编写,同时避免了传统的JDBC中的大量模板代码,提高了开发效率和代码的可维护性。在本文中,我们...
Log4j2是一款广泛使用的Java日志记录框架,它的出现是为了替代早期的Log4j,提供了更为高效、灵活和安全的日志处理能力。这篇随笔主要探讨了Log4j2的一些新特性,对于理解并利用这些特性来优化日志管理至关重要。 ...
JavaThings-Java安全漫谈笔记相关《 Java安全漫谈》是我在写的一点Java学习相关的随笔,不是很严谨,也不是啥高科技。这个存储库主要是记录并整理一下,附加一些代码。Java安全漫谈目录 人口统计字节码:远程字节码...
基于JAVA幼儿园家园共育平台设计与实现 开发语言 JavaWeb前端语言 开发工具:六年特雷利JIDEA ...童言稚语:每月记录一次幼儿有趣的话语,文字展示。 育儿头条:育儿新闻文章。管理员上传,可评论点赞
标题"阶段程序汇总"表明这是一个关于学习Java过程中的阶段性成果集合,可能包含了作者在学习过程中遇到的问题、解决方法以及一些基础的代码示例。 描述中提到,作者整理了学习笔记和简单的Java实例,这些都是学习...
一杯82年的JAVA 大家好,我是练习时常两年半的JAVA练习生,爱好是 Coding、Technology、Reading、Learning 博客专用仓库,主要记录一些学习和实践的总结,感兴趣的朋友可以点个watch或star。 随笔 探索JAVA并发 从...
1. **技术基础知识**:随笔可能涵盖基础的编程语言知识,如Python、Java或C++的语法特性,数据结构和算法的应用,以及软件工程的基本原则。 2. **项目经验分享**:作者可能会分享他们在实际项目中遇到的问题及解决...
列表参考国光大佬的国光的安全随笔记录 安全技能 该技能表不用按顺序进行学习,但是比较高级的我会放最后面,因为我也不会,需要花时间慢慢加。 总结我这几年的一点经验:安全需要学习的技术太多了,特别是红队、...
- **定义**:`ThreadGroup`是Java中用于管理一组线程的类。它提供了一种将多个线程组织在一起进行管理的方式。 - **创建**:通过`new ThreadGroup(groupName)`创建一个新的线程组。其中`groupName`为线程组的名称。 ...
书签心情随笔则让用户记录阅读感受,增添互动性。 通过上述设计,这款阅读软件将不仅满足用户获取信息的需求,还可能成为他们情感共鸣和自我提升的平台。在研究过程中,我们将解决如何准确分析用户阅读习惯、如何...
3. 在代码中使用:在Java代码中,通过Logger类获取日志实例,然后调用如info(), warn(), error()等方法记录日志。 四、日志子文件Logger 压缩包中的"Logger"可能是具体的日志实现类或配置文件。如果是类文件,它...