1.lambda表达式

1.定义

Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),可以推导出来的就可以省略了,Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

2.例子
//一个线程的创建可以使用这种方法
new Thread(() -> System.out.println("多线程任务执行!")).start();
3.标准格式

标准格式3个部分:

一些参数

一个箭头

一段代码

(参数类型 参数名称) ‐> { 代码语句 } 强调的是做什么而不是怎么做

Runnable接口简化:
1. () ‐> System.out.println("多线程任务执行!")
Comparator接口简化:
2. Arrays.sort(array, (a, b) ‐> a.getAge() ‐ b.getAge());
4.前提条件
1.必须有接口,接口中有且仅有一个方法 --函数式接口一定可以的(但不限于)
2.必须有固定的格式,就是参数什么的固定的,可以推断出来
3.

2.Stream流

1.什么是stream流

​ Stream流不同于InputStream和OutputStream.Jdk8中的Stream流是对集合(Collerction)的增强,增强了对集合对象的聚合操作,Stram API借助于Lambda表达式,他提供了串行和并行使用fork/join并行来拆分

2.常用
1.集合获取stream流的方式
Stream<T> stream()
Stream<T> parallelStream()
2. 数组获取stream流的方式
Stream<T> Stream.of(T[])
Stream<T> Arrays.stream(T[]);
3. 文件获取stream流
BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
Stream<String> linesStream = bufferedReader.lines();
4.静态方法获取流操作
IntStream rangeStream = IntStream.range(1, 10);
rangeStream.limit(10).forEach(num -> System.out.print(num+","));
IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
intStream.forEach(num -> System.out.print(num+","));
Pipelining中间操作都会返回流对象本身,这样多个操作可以串联成一个管道 forEach() --输出
map --方法用于映射每个元素到对应的结果
filter --方法用于通过设置的条件过滤出元素
limit --获取指定数量的流
public class StreamDemo1 {
public static void main(String[] args) throws FileNotFoundException {
demo1();
}
public static void getStream() throws FileNotFoundException {
List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"};
// 集合获取 Stream 流
Stream<String> nameListStream = nameList.stream();
// 集合获取并行 Stream 流
Stream<String> nameListStream2 = nameList.parallelStream();
// 数组获取 Stream 流
Stream<String> nameArrStream = Stream.of(nameArr);
// 数组获取 Stream 流
Stream<String> nameArrStream1 = Arrays.stream(nameArr);
// 文件流获取 Stream 流
BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
Stream<String> linesStream = bufferedReader.lines(); // 从静态方法获取流操作
IntStream rangeStream = IntStream.range(1, 10);
rangeStream.limit(10).forEach(num -> System.out.print(num+","));
IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
intStream.forEach(num -> System.out.print(num+","));
} /**
* 1. 筛选出名字长度为4的
2. 名字前面拼接 This is
3. 遍历输出
*/
public static void demo1(){
List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
nameList.stream()
.filter(name -> name.length() == 4)
.map(name -> "This is "+name)
.forEach(name -> System.out.println(name));
}
/**
* 转换成为大写然后收集结果,遍历输出
*/
public static void demo2(){
List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
List<String> collect = nameList.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
collect.forEach(name-> System.out.println(name+","));
}
/**
* 把数字值乘以2
*/
public void mapTest() {
List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// 映射成 2倍数字
List<Integer> collect = numberList.stream()
.map(number -> number * 2)
.collect(Collectors.toList());
collect.forEach(number -> System.out.print(number + ","));
System.out.println();
numberList.stream()
.map(number -> "数字 " + number + ",")
.forEach(number -> System.out.print(number));
}
/**
* flatmap把对象扁平化
*/
public void flatMapTest() {
Stream<List<Integer>> inputStream = Stream.of(
Arrays.asList(1),
Arrays.asList(2, 3),
Arrays.asList(4, 5, 6)
);
List<Integer> collect = inputStream
.flatMap((childList) -> childList.stream())
.collect(Collectors.toList());
collect.forEach(number -> System.out.print(number + ","));
} /**
* 遍历输出
*/
public void forEachTest(){
List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numberList.stream().forEach(number -> System.out.print(number+","));
} /**
* filter 数据筛选
* 筛选出偶数数字
*/
public void filterTest() {
List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> collect = numberList.stream()
.filter(number -> number % 2 == 0)
.collect(Collectors.toList());
collect.forEach(number -> System.out.print(number + ","));
} /**
* 查找第一个数据
* 返回的是一个 Optional 对象
*/
public void findFirstTest(){
List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Optional<Integer> firstNumber = numberList.stream()
.findFirst();
System.out.println(firstNumber.orElse(-1));
} /**
* Stream 转换为其他数据结构
*/
public void collectTest() {
List<Integer> numberList = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5);
// to array
Integer[] toArray = numberList.stream()
.toArray(Integer[]::new);
// to List
List<Integer> integerList = numberList.stream()
.collect(Collectors.toList());
// to set
Set<Integer> integerSet = numberList.stream()
.collect(Collectors.toSet());
System.out.println(integerSet);
// to string
String toString = numberList.stream()
.map(number -> String.valueOf(number))
.collect(Collectors.joining()).toString();
System.out.println(toString);
// to string split by ,
String toStringbJoin = numberList.stream()
.map(number -> String.valueOf(number))
.collect(Collectors.joining(",")).toString();
System.out.println(toStringbJoin);
} /**
* 使用流操作和不使用流操作的编码风格对比
*/
public void diffTest() {
// 不使用流操作
List<String> names = Arrays.asList("Jack", "Jill", "Nate", "Kara", "Kim", "Jullie", "Paul", "Peter");
// 筛选出长度为4的名字
List<String> subList = new ArrayList<>();
for (String name : names) {
if (name.length() == 4) {
subList.add(name);
}
}
// 把值用逗号分隔
StringBuilder sbNames = new StringBuilder();
for (int i = 0; i < subList.size() - 1; i++) {
sbNames.append(subList.get(i));
sbNames.append(", ");
}
// 去掉最后一个逗号
if (subList.size() > 1) {
sbNames.append(subList.get(subList.size() - 1));
}
System.out.println(sbNames);
System.out.println("----------------"); // 使用 Stream 流操作
String nameString = names.stream()
.filter(num -> num.length() == 4)
.collect(Collectors.joining(", "));
System.out.println(nameString); // String string = names.stream().filter(num -> num.length() == 4).map(name -> name.toUpperCase()).collect(Collectors.joining(","));
String string = names.stream()
.filter(num -> num.length() == 4)
.map(name -> name.toUpperCase())
.collect(Collectors.joining(","));
} /**
* reduce 字符串拼接例子
*/
public void reduceTest() {
List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python");
String s = skills.stream().reduce((all, skill) -> all + skill).get();
System.out.println(s);
} /**
* 数据去重例子
*/
public void distinctTest() {
List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
List<String> collects = skills.stream().distinct().collect(Collectors.toList());
collects.forEach(skill -> System.out.println(skill));
System.out.println("---------------------------------------------");
skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
skills.stream().distinct().forEach(s -> System.out.println(s));
} /**
* 数学计算测试
*/
public void mathTest() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics();
System.out.println("最小值:" + stats.getMin());
System.out.println("最大值:" + stats.getMax());
System.out.println("个数:" + stats.getCount());
System.out.println("和:" + stats.getSum());
System.out.println("平均数:" + stats.getAverage());
} /**
* 按年龄分组
*/
public void groupByTest() {
List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
Map<String, List<Integer>> ageGrouyByMap = ageList.stream()
.collect(Collectors.groupingBy(age -> String.valueOf(age / 10))); ageGrouyByMap.forEach((k, v) -> {
System.out.println("年龄" + k + "0多岁的有:" + v);
});
} /**
* 按某个条件分组
* 给一组年龄,分出成年人和未成年人
*/
public void partitioningByTest() {
List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
Map<Boolean, List<Integer>> ageMap = ageList.stream()
.collect(Collectors.partitioningBy(age -> age > 18));
System.out.println("未成年人:" + ageMap.get(false));
System.out.println("成年人:" + ageMap.get(true));
} /**
* 生成自己的 Stream 流
*/
public void generateTest(){
// 生成自己的随机数流
Random random = new Random();
Stream<Integer> generateRandom = Stream.generate(random::nextInt);
generateRandom.limit(5).forEach(System.out::println); // 生成自己的 UUID 流
Stream<UUID> generate = Stream.generate(UUID::randomUUID);
generate.limit(5).forEach(System.out::println);
} /**
* 获取 / 扔掉前 n 个元素
*/
public void limitOrSkipTest() {
// 生成自己的随机数流
List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
ageList.stream()
.limit(3)
.forEach(age -> System.out.print(age+","));
System.out.println(); ageList.stream()
.skip(3)
.forEach(age -> System.out.print(age+","));
} /**
* 找出偶数
*/
public void lazyTest() {
// 生成自己的随机数流
List<Integer> numberLIst = Arrays.asList(1, 2, 3, 4, 5, 6);
// 找出第一个偶数
Stream<Integer> integerStream = numberLIst.stream()
.filter(number -> {
int temp = number % 2;
if (temp == 0 ){
System.out.println(number);
}
return temp == 0;
}); System.out.println("分割线");
List<Integer> collect = integerStream.collect(Collectors.toList());
} /**
* 并行计算
*/
public void main() {
// 生成自己的随机数流,取一千万个随机数
Random random = new Random();
Stream<Integer> generateRandom = Stream.generate(random::nextInt);
List<Integer> numberList = generateRandom.limit(10000000).collect(Collectors.toList()); // 串行 - 把一千万个随机数,每个随机数 * 2 ,然后求和
long start = System.currentTimeMillis();
int sum = numberList.stream().map(number -> number * 2).mapToInt(x -> x).sum();
long end = System.currentTimeMillis();
System.out.println("串行耗时:"+(end - start)+"ms,和是:"+sum); // 并行 - 把一千万个随机数,每个随机数 * 2 ,然后求和
start = System.currentTimeMillis();
sum = numberList.parallelStream().map(number -> number * 2).mapToInt(x -> x).sum();
end = System.currentTimeMillis();
System.out.println("并行耗时:"+(end - start)+"ms,和是:"+sum); } public void simpleTest(){
List<Integer> numbers = Arrays.asList(1, 2, 3);
int[] factor = new int[] { 2 };
Stream<Integer> stream = numbers.stream()
.map(e -> e * factor[0]);
factor[0] = 0;
stream.forEach(System.out::println);
} }

3.函数式接口

1.定义

函数式接口就是有且仅有一个抽象方法的接口,java中的函数式编程就是Lambda,函数式接口可以使用于lambda表达式中,

2.格式
修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
//public abstract 在抽象接口中的方法修饰上是可以省略的
}
3.例子
public interface MyFunctionalInterface {
void myMethod();
}
public class FunctionalInterface {
// 使用自定义的函数式接口作为方法参数
private static void doSomething(MyFunctionalInterface inter) {
inter.myMethod(); // 调用自定义的函数式接口方法
}
public static void main(String[] args) {
// 调用使用函数式接口的方法
doSomething(()-> System.out.println("Lambda执行啦!"));
}
}
4.自定义
与@Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface。该注解可用于一个接口的定义上
如果不使用这个注解,如果仍然满足要求,一样可以用,但是加上就必须满足,不然会报错
5.常用 java.util.function
1.Supplier接口

java.util.function.Supplier 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据

@FunctionalInterface
public interface Supplier<T> {
T get();
}
调用这个方法就要返回一个T类型的数据,至于这个数据是如何加工出来的,可以自定义,所以是生产者

例子

public interface MyFunctionalInterface {
void myMethod();
} public class FunctionalInterface {
// 使用自定义的函数式接口作为方法参数
private static void doSomething(MyFunctionalInterface inter) {
inter.myMethod(); // 调用自定义的函数式接口方法
}
public static void main(String[] args) {
// 调用使用函数式接口的方法
doSomething(()-> System.out.println("Lambda执行啦!"));
}
}
2.Consumer接口

java.util.function.Consumer 接口则正好相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛

型参数决定。

@FunctionalInterface
public interface Consumer<T> {
//消费一个对象
void accept(T t); //再次消费一个对象
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

例子

public class ConsumerDemo {
private static void consumeString(Consumer<String> one,Consumer<String> two) {
one.andThen(two).accept("hello");
one.accept("ddd");
} public static void main(String[] args) {
consumeString(s-> System.out.println(s.toUpperCase()),s-> System.out.println(s.toLowerCase()));
}
}
3.Predicate接口

java.util.function.Predicate 有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。

@FunctionalInterface
public interface Predicate<T> {
//用于判断
boolean test(T t); //既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起 //来实现“并且”的效果时,可以使用default方法 and
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
} //它是执行了test方法之后,对结果boolean值进行“!”取反而已。一定要在调用test方法之前调用negate
default Predicate<T> negate() {
return (t) -> !test(t);
} //or或者进行比较 在调用test之前调用or
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
} static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
public class PredicateAndTest {
public static void main(String[] args) {
//methodAnd(s-> s.contains("H"), s-> s.contains("y"),"Helloworld");
//methodOr(s-> s.contains("a"), s-> s.contains("y"),"Helloworld");
methodNegate(s-> "Helloworld".equals(s),"Helloworld");
}
private static void methodAnd(Predicate<String> one,Predicate<String> two,String str) {
boolean test = one.and(two).test(str);
System.out.println("字符串符合要求吗:" + test);
}
private static void methodOr(Predicate<String> one,Predicate<String> two,String str){
boolean test = one.or(two).test(str);
System.out.println("字符串符合要求吗or:" + test);
}
private static void methodNegate(Predicate<String> one,String str){
boolean test = one.negate().test(str);
System.out.println("字符串取反:" + test);
}
}
4.Function<T,R> 接口

简单的说就是类型转换,就是一种类型的数据转换成为另外一个类型的数据,把T类型的转换成R类型的,有进有出

@FunctionalInterface
public interface Function<T, R> {
//根据类型T的参数获取类型R的结果
R apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
//用来进行组合操作 类似于Consumer 中的andThen
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
} static <T> Function<T, T> identity() {
return t -> t;
}
}

例子

public class FunctionDemo {
public static void main(String[] args) {
method(s -> Integer.parseInt(s),"10");
method2(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return 1;
}
});
methodAddthen(s -> Integer.parseInt(s),s->s+10,"1");
}
//String 转换成Integer类型的
private static void method(Function<String, Integer> function, String str) {
int num = function.apply(str);
System.out.println(num + 20);
}
private static void method2(Function<String, Integer> function) {
int num = function.apply("33");
System.out.println(num + 20);
}
private static void methodAddthen(Function<String, Integer> one,Function<Integer, Integer> two,String str) {
Integer apply1 = one.andThen(two).apply(str);
System.out.println(apply1 + 20);
}
}

JDK8中的新特性的更多相关文章

  1. ASP.NET 5与MVC 6中的新特性

    差点忘了提一句,MVC 6中默认的渲染引擎Razor也将得到更新,以支持C# 6中的新语法.而Razor中的新特性还不只这一点. 在某些情况下,直接在Web页面中嵌入某些JSON数据的方式可能比向服务 ...

  2. Webpack 3 中的新特性

    本文简短地分享下最新发布的 Webpack 3 中的新特性,供大家参考. 1. Webpack 3 的新特性 6 月 20 日,Webpack 发布了最新的 3.0 版本,并在 Medium 发布了公 ...

  3. 使用示例带你提前了解 Java 9 中的新特性

    使用示例带你提前了解 Java 9 中的新特性 转载来源:https://juejin.im/post/58c5e402128fe100603cc194 英文出处:https://www.journa ...

  4. HTML 5中的新特性

    HTML 5中的新特性 html5新增了一些语义化更好的标签元素.首先,让我们来了解一下HTML语义化. 1.什么是HTML语义化? 根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开 ...

  5. (数据科学学习手札73)盘点pandas 1.0.0中的新特性

    本文对应脚本及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 毫无疑问pandas已经成为基于Pytho ...

  6. 1 PHP 5.3中的新特性

    1 PHP 5.3中的新特性 1.1 支持命名空间 (Namespace) 毫无疑问,命名空间是PHP5.3所带来的最重要的新特性. 在PHP5.3中,则只需要指定不同的命名空间即可,命名空间的分隔符 ...

  7. JDK7和JDK8一些重要新特性

    jdk7新特性(部分) switch支持字符串 List AutoCloseable接口实现自动关闭,在try()中 新增获取环境信息的工具方法,getJavaHomeDir,getUserHomeD ...

  8. dk7和jdk8的一些新特性

    本文是我学习了解了j 的一些资料,有兴趣的大家可以浏览下下面的内容. 官方文档:http://www.oracle.com/technetwork/java/javase/jdk7-relnotes- ...

  9. JDK8~JDK11的新特性

    #JDK 1.8 新特性接口中的静态方法 只能由接口自己调用 接口中的默认方法 可以不被覆盖 #JDK 1.9 新特性(可能在JDK8中被忽略了,没来得及加)接口可以定义私有方法,但是只能让自己调用, ...

随机推荐

  1. Regression 回归——多项式回归

    回归是指拟合函数的模型.图像等.与分类不同,回归一般是在函数可微的情况下进行的.因为分类它就那么几类,如果把类别看做函数值的话,分类的函数值是离散的,而回归的函数值通常是连续且可微的.所以回归可以通过 ...

  2. i春秋-百度杯九月场-YeserCMS(cmseasy的UpdateXML注入漏洞)

    学习了大佬们的操作才做出来,记录一次菜鸡的无能为力. tips:flag在网站根目录下的flag.php中.我们的目标就是flag.php了. 题目说是心的CMS:YeserCMS,然而百度一下,出来 ...

  3. UVA10820 交表 Send a Table

    \(\Large\textbf{Description:} \large{输入n,求有多少个二元组(x,y)满足:1\leqslant x,y\leqslant n,且x和y互素.}\) \(\Lar ...

  4. jackson处理json

    原文连接 工具下载: jackson-core-2.2.3.jar 核心jar包,下载地址 jackson-annotations-2.2.3.jar 该包提供Json注解支持,下载地址 jackso ...

  5. html基础与入门

    html就是指一个html文件,它是由各种标签组成的 html分为 < !DOCTYPE html > 和 Head 和 Body Head title+meta+link+style B ...

  6. HashMap之Hash碰撞源码解析

    转自:https://blog.csdn.net/luo_da/article/details/77507315 https://www.cnblogs.com/tongxuping/p/827619 ...

  7. Java 布尔运算

    章节 Java 基础 Java 简介 Java 环境搭建 Java 基本语法 Java 注释 Java 变量 Java 数据类型 Java 字符串 Java 类型转换 Java 运算符 Java 字符 ...

  8. LCD驱动详解

    参考文档:<液晶屏.pdf><S3C2440用户手册><JZ2440-V3原理图>   frame buffer: 显存,用于存放LCD显示数据:frame buf ...

  9. Codeforces1243C Tile Painting

    原题面:https://codeforces.com/contest/1243/problem/C 题目大意:给定数字n,有n个方块,第i个和第j个之间的距离(abs(i-j))如果是n的因子,那么第 ...

  10. C语言备忘录——qsort

    写了这么久的排序感觉还是用现成的最舒服.其实C语言其实自己带了一个快速排序在stdlib 库里,但是其函数调用的接口过于复杂,所以让人望而却步.为了加深自己的记忆,所以写下这篇博客 先来看一下函数原型 ...