友情提示:java8和ES6的内容很多,本文简单介绍几个方法。来替代项目中的for循环
这里展示两段代码,具体代码没什么意义,主要看代码的行数,与结构
有木有精简很多!!!有木有逼格高了很多!!!有木有看不懂了很多!!!
为啥要把Java8Lambda和ES6箭头函数联系在一起说呢?
因为他们真的太像了,虽然java和javascipt就像是老婆和老婆饼一样没什么关系的两个语言。
但他们却又很多地方都是神类似的。
来看看Lambda和ES6的到底有哪些一样的方法?
创建一个Main类,在类中添加如果下代码,此方法主要用于替代 System.out.println输出信息
后面的所有 log()==System.out.println();
//System.out.println的简化版
public static void log(Object object) {
System.out.println(object);
}
jdk1.8之前的函数式接口有哪些?
java.lang.Runable
java.util.concurrent.Callable
java.util.Comparatorjdk1.8之后的函数式接口有哪些?
Supplier 一个输出
Consumer 一个输入
BiConsumer 两个输入
Function 一个输入,一个输出(类型可能不同)
BiFunction 两个输入,一个输出(类型可能不同)
UnaryOperator 一个输入,一个输出(输入输出的类型是一致的)
BinaryOperator 两个输入,一个输出(输入输出的类型是一致的)
public static void testLambda1() {
Supplier<Integer> f1 = () ->{return 100;};//只有返回值没有输入
Supplier<String> f2 = () -> {return "返回值";};
log(f1.get());
log(f2.get());
Consumer<String> f3 = (arg)->{log(arg);};//只有输入没有返回值
f3.accept("输入");
Consumer<String> f4 = arg->log(arg); //只有一个参数一行语句时可省略参数的()和返回值的{}
f4.accept("输入");
Function<String, Integer> f5 = arg -> arg.length();//一个输入参数一个返回值
log(f5.apply("输入"));
BiFunction<String, String, Integer> f6 =
(arg1,arg2)->arg1.length()+arg2.length();//两个输入一个返回值
log(f6.apply("aa", "bbb"));
new Thread(()->log("子线程输出语句"));//创建一个子线程输出一句话
System.out.println("主线程输出语句");
}
public static void testLambda2() {
//Supplier的中文意思是提供,对应的用法是 无参有返回值
Supplier<String> f1 = Main::test1;
System.out.println(f1.get());
//Consumer的中文意思是消费,对应的用法是 有参无返回值
Consumer<String> f2 = Main::test2;
f2.accept("传入参数");
//function的中文意思是函数,对应的用法是 一个参数,有返回值
Function<String, String> f3 = Main::test3;
log(f3.apply("传入参数"));
//function的中文意思是函数,对应的用法是 二个参数,有返回值
BiFunction<String, String, String> f4 = Main::test4;
log(f4.apply("参数1", "参数2"));
}
public static String test1() {
return "aa";
}
public static void test2(String args) {
log(args);
}
public static String test3(String args) {
log(args);
return "返回值";
}
public static String test4(String arg1,String arg2) {
log(arg1+"|"+arg2);
return "返回值";
}
public static void streamApi() {
log("stream1------------");
String[] arr = {"a","b","c"};
Stream<String> stream1 = Stream.of(arr);//数组转Stream
stream1.forEach(Main::log);//便利输出每一个元素
log("stream2------------");
List<String> list = Arrays.asList("1","2","3");
Stream<String> stream2 = list.stream();//List转Stream
stream2.forEach(Main::log);//便利输出每一个元素
log("stream3------------");
Stream<String> stream3 = Stream.generate(()->"a");//生产"a"的字符串
stream3.limit(5).forEach(Main::log);//limit是截取,截取并输出
log("stream4------------");
Stream<Integer> stream4 = Stream.iterate(1, x->x+1);//迭代器,从1开始,一次+1,类似i++
stream4.limit(5).forEach(Main::log);//limit是截取,截取并输出
log("stream5------------");
String str = "abc";
IntStream stream5 = str.chars();//字母变成了对应的字符编码
// stream5.forEach(item -> System.out.println(item));//lambda箭头函数写法
// stream5.forEach(System.out::println);//lambda方法体只有一句话时的简写形式
stream5.forEach(Main::log);//由于本类中又静态的log输出方法,所以可以这样写
}
一种是返回值依然是Stream对象的。如下
过滤filter
去重distinct
排序sorted
截取limit、skip
转换map/flatMap
窥视peek
另一种是没有返回的。如下
循环forEach
计算min、max、count、average
匹配anyMatch、allMath、noneMathch、findFirst、findAny
汇集reduce
收集器toArray collect
准备两个对象,此处省略了get set方法
class User {
String username;
String password;
}
class Person {
String name;
String nikename;
int age;
}
测试代码
public static void streamApiActualCombat() {
//例子0 使用filter方法取偶数
log("例子0 使用filter方法取偶数--------------------------------------------");
Arrays.asList(1,2,3,4,5,6,7).stream().filter(item -> item%2==0).forEach(Main::log);
/*
* 先使用Arrays.asList把一堆元素变成一个List,然后获取stream对象,调用filter方法
* filter方法于forEach类似的一点,也是每次拿一个元素,也是会把所有的元素便利一遍
* 每次执行时判断条件是否成立最后返回true或false;
* 最后过滤好剩余的元素其实还在stream中,
* 如果需要,可以使用.collect(Collectors.toList())进行收集,返回一个List
* 也可以直接foreach输出。
* */
//例子1 字符串转换Map
log("例子1 字符串转换Map--------------------------------------------");
String queryString = "itemId=1&userId=10000&type=20&token=1111111&key=index";
Map<String, String> param = Stream.of(queryString.split("&"))
.map(str -> str.split("="))
.collect(Collectors.toMap(s->s[0], s->s[1]));
log(param);
//例子2 list重构
log("例子2 list重构--------------------------------------------");
List<User> users = new ArrayList<>();
users.add(new User("张三","123456"));
users.add(new User("李四","123456"));
users.add(new User("张三","123456"));
users.add(new User("赵六","123456"));
users.forEach(Main::log);
//例子3 list重构,只获取username字段,并重组
log("例子3 list重构,只获取username字段,并重组--------------------------------------------");
List<String> names = users.stream().map(u->u.getUsername()).collect(Collectors.toList());
names.forEach(Main::log);
//例子4 list重构,只获取username字段,并重组
log("例子4 list重构,只获取username字段,并重组--------------------------------------------");
List<String> pass = users.stream().map(u->u.getPassword()).collect(Collectors.toList());
pass.forEach(Main::log);
//例子5 数组聚合,name转User对象
log("例子5 数组聚合,name转User对象--------------------------------------------");//两个数组重构成一个数组,前提需要有相应的临时包装类
List<JSONObject> users2 = Stream.iterate(0, i -> i + 1).limit(names.size()).map(i->{
String name = names.get(i);
String password = 1000+""+i;
User user = new User(name,password);
// return user;
JSONObject jo = new JSONObject();
jo.put(name, names.get(i));
jo.put("password", 1000+""+i);
jo.put("index", i);
return jo;
}).collect(Collectors.toList());
log(users2);
//例子6重构时同时去重
log("例子6 重构时同时去重--------------------------------------------");
List<String> namesSingle = users.stream().map(u->u.getUsername()).distinct().collect(Collectors.toList());
namesSingle.forEach(Main::log);
//例子7 使用普通的set去重
log("例子7 使用普通的set去重--------------------------------------------");
Set<String> nameSet = names.stream().collect(Collectors.toSet());
nameSet.forEach(Main::log);
//例子8 使用普通的set去重
log("例子8 数组聚合简单版,user转map--------------------------------------------");
Map<String,User> map = userSimple.stream().collect(Collectors.toMap(user->user.getUsername(), user->user));
log(map);
//例子9 根据username统计User列表
log("例子9 根据username统计User列表--------------------------------------------");
Map<String, Long> map2 = users.stream().collect(Collectors.groupingBy(User::getUsername,Collectors.counting()));
log(map2);
//例子10 根据年龄字段获取年龄最大的那个对象
log("例子10 根据年龄字段获取年龄最大的那个对象--------------------------------------------");
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三","张三丰",18));
persons.add(new Person("张三","张三丰",18));
persons.add(new Person("张三","张三丰",18));
persons.add(new Person("李四","李四叔",33));
persons.add(new Person("王五","王五弟",25));
persons.add(new Person("赵六","昵称六",19));
Optional<Person> maxAge = persons.stream().collect(Collectors.maxBy(Comparator.comparing(Person::getAge)));
log(maxAge.get());
//例子11 用name分组,然后根据同名的年龄和
log("例子11 用name分组,然后根据同名的年龄和--------------------------------------------");
Map<String, Double> map3 = persons.stream().collect(Collectors.groupingBy(Person::getName,Collectors.summingDouble(Person::getAge)));
log(map3);
//例子12 peek窥视(连续)操作
log("例子12 peek窥视(连续)操作--------------------------------------------");
String[] strings = {"a","bb","ccc","dddd","eeee"};
Stream.of(strings).peek(Main::log)
.filter(str->str.length()>3)
.forEach(Main::log);
<html>
<head>
<title>ES6数组title>
<script type="text/javascript">
// ES6数组新添加的一些方法:
// arr.forEach() //循环遍历
// arr.map() //有返回值得遍历
// arr.filter() //过滤一个新数组
// arr.some() //查找
// arr.every() //满足
// arr.reduce() //一般叠加用
// arr.reduceRight() //同上
// arr.find() //查找,并返回符合条件的第一个对象,否则返回undefined
//类似arr.findIndex('str') 返回第一次出现的下标,否则返回-1 ES5老函数
//arr.fill('str',startindex,endindex);//在某个位置插入一个成员
//arr.includes()//数组查找某个成员是否存在 类似字符串中的includes函数 返回boolean
//for of [ES6版本] forEach的简化版
//for in [老版本] forEach的简化版
// java中的foreach;
// Python中的 for in;
// js 中的for of;遍历数组,set//for in遍历对象
// Array、Object、Set、Map四种数据结构中for、for in和for of循环的区别?
// 一、普通for循环在Array和Object中都可以使用。
// 二、for in在Array和Object中都可以使用。// 注意:在对象中包含原型上的属性。
// 三、for of在Array、Object、Set、Map中都可以使用。
// 四、forEach循环在Array、Set、Map中都可以使用。
// arr.forEach()
let arr=['apple','banana','orange','tomato'];
//传统写法
// for (var i = 0; i < arr.length; i++) {
// console.log(arr[i]);
// }
//ES6 forEach写法
//参数说明:forEach函数的参数一:是一个函数,参数二:方法内this指向(不常用) 如果不指定默认window
//forEach会向这个函数传入三个参数
//(当前值,当前下标,所在数组)
// arr.forEach(function(val,index,arr,tem){
// console.log(val,index,arr,tem);
// });
// 输出结果:
// apple 0 ["apple", "banana", "orange", "tomato"] undefined
// banana 1 ["apple", "banana", "orange", "tomato"] undefined
// orange 2 ["apple", "banana", "orange", "tomato"] undefined
// tomato 3 ["apple", "banana", "orange", "tomato"] undefined
//ES6 forEach+箭头函数写法
//参数说明:forEach函数的参数一:是一个函数,参数二:箭头函数时此参数无效
//forEach会向这个函数传入三个参数
//(当前值,当前下标,所在数组)
// arr.forEach((val,index,arr)=>{
// console.log(val,index,arr);
// });
// 输出结果:
// apple 0 ["apple", "banana", "orange", "tomato"]
// banana 1 ["apple", "banana", "orange", "tomato"]
// orange 2 ["apple", "banana", "orange", "tomato"]
// tomato 3 ["apple", "banana", "orange", "tomato"]
// arr.map()
// map的重要作用:重置数据结构 //map没有返回值得时候和forEach()方法一模一样
//有返回值的时候 是每个function都会返回一个值,最终形成一个数组,返回
//let newarr=arr.forEach()//返回的是undefined
//let newarr=arr.map()//返回的是每个function 返回值 组成的数组(可能是普通数组,也可以能对象数组)
let arr2=[
{title:'aaaaa',read:100,hot:true},
{title:'bbbbb',read:100,hot:true},
{title:'ccccc',read:100,hot:true},
{title:'ddddd',read:100,hot:true}
];
let newarr2=arr2.map((item,index,arr)=>{
//console.log(item,index);
return {
index:index,
title:item.title,
read:item.read,
hot:item.hot
}
});
console.log(newarr2);
//总结map的重要作用:重置数据结构
//用需要返回值用map不需要返回值用forEach
//arr.filter()
//主要作用:过滤 返回值 true||false true留下 false删除
// 最后返回一个过滤好的新数组
let arr3=[
{title:'aaaaa',read:100,hot:true},
{title:'bbbbb',read:100,hot:false},
{title:'ccccc',read:100,hot:true},
{title:'ddddd',read:100,hot:false}
];
let newarr3=arr3.filter((item,index,arr)=>{
//console.log(item,index);
return item.hot;
});
console.log(newarr3);
//arr.some() //子函数返回 boolean 最后根据boolean数组||运算 即只要一个满足就返回true
//arr.every() //子函数返回 boolean 最后根据boolean数组&&运算 即必须每一个满足才返回true
let arr4=[1,2,3,4,5,6,7,8,9,10];
let res1=arr4.reduce((pre,cur,idnex,arr)=>{//会传一个上一个元素的值
return pre+cur;
});
console.log(res1);//55
let arr5=[1,2,3,4,5,6,7,8,9,10];
let res2=arr5.reduceRight((pre,cur,idnex,arr)=>{//同上,但是这个是从右往左遍历数组
return pre+cur;
});
console.log(res2);//55
// Array.find()//查找 参数是一个函数,函数做判断条件满足条件就返回当前对象,如果没找到,返回 undefined
let arr7=[23,900,102,80];
let res=arr7.find((val,index,arr)=>{
return val>100;
});
console.log(res);//返回第一个符合条件的
//ES6.2(ES8) 2017版本
//幂运算符2**3 相同与 Math.pow(2,3);
//for of
let arr6=["apple", "banana", "orange", "tomato"];
for(let val of arr6){
console.log(val);
}
//这是一种错误的写法,因为有了上面的下方,所以下面的这个不存在的
// for(let val of arr6.values()){
// console.log(val);
// }
for(let index of arr6.keys()){
console.log(index);
}
for(let item of arr6.entries()){
console.log(item);
}
for(let [key, val] of arr6.entries()){ //解构写法
console.log(key,val);
}
//----------------------------------------------------------------------------------------
//数组其他知识:
// Array.from()
let jsonstr={
8:'aaaaaa',
6:'bbbbbb',
2:'cccccc',
3:'dddddd',
length:10
}
let newarr=Array.from(jsonstr);
console.log(newarr);
// Array.of()//把多个值合并成一个数组 Array.of(1,2,3) 返回[1,2,3]
/*------------------------------------------------------------
一个很帅很装逼却没有什么用的知识点:
Array.from() //参数:类数组 返回一个数组
把一个类似数组的对象转换成数组
//from转换的关键在于 预转换的对象内是否有length这个属性 和属性的key
只有满足有lenth这个属性,而且key 为整形才行
let json={
0:'aaaa',
1:'bbbb'
}
let newarr=Array.from(json);//newarr 为 []
let jsonstr={
8:'aaaaaa',
6:'bbbbbb',
2:'cccccc',
3:'dddddd',
length:10
}
let newarr=Array.from(jsonstr);
console.log(newarr);//newarr 为
[undefined, undefined, "cccccc", "dddddd", undefined, undefined, "bbbbbb", undefined, "aaaaaa", undefined]
------------------------------------------------------------*/
script>
head>
<body>
body>
html>
ES6原文链接
https://www.cnblogs.com/bigfire/p/9518100.html
优点:
缺点: