目录
1.Lambda表达式与函数式接口
1.Lambda表达式简介
2.Lambda表达式的用法
3.函数式接口简介
4.默认方法与静态方法
5.四大常用的函数式接口
2.方法引用
1.构造器引用
2.静态方法引用
3.任意对象的方法引用
4.特定对象的方法引用
3.Optional
1.Optional的三种构造方式
2.Optional的错误使用
3.Optional的常见用法
4.Stream
1.Stream简介
2.常用惰性求值方法
3.常用及早求值方法
5.Collector
1.转换成其他集合
2.转换成值
3.数据分块
4.数据分组
5.字符串
6.组合收集器
7.定制收集器
作者:刘仁鹏
参考资料:
Arrays.asList("a", "b", "c").forEach((String item) -> System.out.println(item));
Arrays.asList("a", "b", "c").forEach(item -> System.out.println(item));
Arrays.asList("a", "b", "c").forEach(
new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
}
);
Arrays.asList("a", "b", "c").forEach((String item) -> {
System.out.println(item);
System.out.println(item);
});
public class Test {
private int num = 1;
public static void main(String[] args) {
String separator = ",";
Test test = new Test();
Arrays.asList("a", "b", "c").forEach(
item -> System.out.println(item + separator + test.num));
//separator = ";";
//编译期错误 Variable used in lambda expression should be final or effectively final
//test = new Test();
//编译期错误 Variable used in lambda expression should be final or effectively final
}
}
Arrays.asList("a", "b", "c").sort((s1, s2) -> s1.compareTo(s2));
Arrays.asList("a", "b", "c").sort((s1, s2) -> {
return s1.compareTo(s2);
});
@FunctionalInterface
public interface TestFunctional{
void method();
}
@FunctionalInterface
public interface Ruler {
/**
* 校验T
*/
void check(T checkTarget);
/**
* 或操作
*/
@SuppressWarnings("unchecked")
default Ruler or(Ruler... rulers) {
return checkTarget -> {
try {
check(checkTarget);
} catch (CheckException e) {
ofAll(rulers).check(checkTarget);
}
};
}
/**
* Ruler整合
*/
@SafeVarargs
static Ruler ofAll(Ruler... rulers) {
return (checkTarget -> Arrays.stream(rulers).forEach(ruler -> ruler.check(checkTarget)));
}
}
/**
* @name 消费型接口
* @use Consumer
* @param T 传入参数
* @fun 接受一个参数 无返回值
* */
Consumer con = (str) -> System.out.println(str);
con.accept("我是消费型接口!");
//输出:我是消费型接口!
/**
* @name 供给型接口
* @use Supplier
* @param R 返回值类型
* @fun 无参数 有返回值
* */
Supplier supp = () -> new Date();
Date date = supp.get();
System.out.println("当前时间:" + date);
//输出:当前时间:Wed Jul 04 08:05:10 CST 2018
/**
* @name 函数型接口
* @use Function
* @param T 传入参数
* @return R 返回值类型
* @fun 接受一个参数 有返回值
* */
Function fun = (str) -> "hello," + str;
String str = fun.apply("tom");
System.out.println(str);
//输出:hello,tom
/**
* @name 断定型接口
* @use Predicate
* @param T 传入参数
* @return Boolean 返回一个Boolean型值
* @fun 接受一个参数 返回Boolean型值
* */
Predicate pre = (num) -> num > 0;
Boolean flag = pre.test(10);
System.out.println(flag);
//输出:true
类型 | 示例 |
---|---|
构造器引用 | Class::new |
静态方法引用 | Class::static_method |
任意对象的方法引用 | instance::method |
特定对象的方法引用 | Class::method |
public static class Car {
public static Car create(final Supplier supplier) {
return supplier.get();
}
public static void collide(final Car car) {
System.out.println("Collided " + car.toString());
}
public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}
public void repair() {
System.out.println("Repaired " + this.toString());
}
}
final Car car1 = Car.create(() -> new Car()); //lambda表达式
final Car car2 = Car.create(Car::new); //方法引用
final List cars = Arrays.asList(car1, car2);
cars.forEach((Car it) -> Car.collide(it)); //lambda表达式
cars.forEach(Car::collide); //方法引用
cars.forEach((Car it) -> it.repair()); //lambda表达式
cars.forEach(Car::repair); //方法引用
final Car police = new Car();
cars.forEach((Car it) -> police.follow(it)); //lambda表达式
cars.forEach(police::follow); //方法引用
使用 isPresent() 方法:
isPresent() 与 obj != null 没有任何分别,并不会使代码变得优雅
使用 get() 方法:
没有 isPresent() 作铺垫的 get() 调用在IDEA中会收到警告
Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception
调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常
Optional 类型作为 类/实例属性 或 方法参数 时:
把 Optional 类型用作属性或是方法参数在 IntelliJ IDEA 中是强力不推荐的
Reports any uses of java.util.Optional
, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not.
使用任何像 Optional 的类型作为字段或方法参数都是不可取的. Optional 只设计为类库方法的, 可明确表示可能无值情况下的 返回类型 . Optional 类型不可被序列化, 用作字段类型会出问题的
错误示例:
//不要这么写:
Optional userOpt = selectUserById(id);
if (userOpt.isPresent()) {
return userOpt.get().getName();
} else {
return "none";
}
//这其实与我们以前不使用Optional时的代码没有任何区别:
User user = getUserById(id);
if (user != null) {
return user.getName();
} else {
return "none";
}
//正确的写法:
return selectUserById(id).map(User::getName).orElse("none");
return opt.orElse(null);
//而不是 return opt.isPresent() ? opt.get() : null;
return user.orElseGet(() -> fetchAUserFromDatabase());
//而不要 return user.isPresent() ? user: fetchAUserFromDatabase();
user.ifPresent(System.out::println);
//而不要
if (user.isPresent()) {
System.out.println(user.get());
}
return selectUserById(id)
.map(u -> u.getUsername())
.map(name -> name.toUpperCase())
.orElse(null);
//在java8之前的版本,等价的写法是这样的:
User user = getUserById(id);
if (user != null) {
String name = user.getUsername();
if (name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
public static void main(String[] args) {
long count1 = Stream.of(1, 2, 3)
.filter(it -> it > 2)
.count();
long count2 = 0;
List list = Arrays.asList(1, 2, 3);
for (Integer it : list) {
if (it > 2) {
count2++;
}
}
System.out.println("count1:" + count1 + "---count2:" + count2);
//输出:count1:1---count2:1
}
// 势能存储
Stream potentialEnergy = Stream.of(1, 2, 3)
.filter(it -> {
System.out.println("hello");
return it > 2;
});
System.out.println("world");
// 势能释放
long count = potentialEnergy.count();
System.out.println("count:" + count);
// 尝试将势能再次释放(抛出异常)
long countAgain = potentialEnergy.count();
System.out.println("countAgain:" + countAgain);
//输出:
//world
//hello
//hello
//hello
//count:1
//java.lang.IllegalStateException: stream has already been operated upon or closed
为方便演示,这里定义了一个字段、两个实体类、一个main方法。下文的示例将放到main方法中,会用到这部分代码。
public class Test {
public static void main(String[] args) {
//示例代码
}
private static List businessList = Arrays.asList(
new Business(1L, "家政", Arrays.asList(
new Category(11L, "保洁"),
new Category(12L, "保姆")
)),
new Business(2L, "速运", Arrays.asList(
new Category(21L, "搬家"),
new Category(22L, "货运")
))
);
@Data
@AllArgsConstructor
static class Business {
private long id;
private String name;
private List categoryList;
}
@Data
@AllArgsConstructor
static class Category {
private long id;
private String name;
}
}
businessList.stream()
.map(Business::getName)
.forEach(System.out::println);
//输出:
//家政
//速运
businessList.stream()
.flatMap(business -> business.getCategoryList().stream())
.forEach(System.out::println);
//输出:
//Test.Category(id=11, name=保洁)
//Test.Category(id=12, name=保姆)
//Test.Category(id=21, name=搬家)
//Test.Category(id=22, name=货运)
businessList.stream()
.filter(business -> business.getId() > 1)
.forEach(System.out::println);
//输出:
//Test.Business(id=2, name=速运, categoryList=[Test.Category(id=21, name=搬家), Test.Category(id=22, name=货运)])
long sumOfCategoryId = businessList.stream()
.flatMap(business -> business.getCategoryList().stream())
.map(Category::getId)
.reduce((x, y) -> x + y).orElse(0L);
System.out.println(sumOfCategoryId);
//输出:66
List categoryIdList = businessList.stream()
.flatMap(business -> business.getCategoryList().stream())
.map(Category::getId)
.collect(Collectors.toList());
System.out.println(categoryIdList);
//输出:[11, 12, 21, 22]
//当希望使用集合对象/实现来收集值时,可以使用toCollection
TreeSet rst = businessList.stream()
.map(Business::getName)
.collect(Collectors.toCollection(TreeSet::new));
System.out.println(rst);
//输出:[家政, 速运]
//获取id值最大的业务线
Optional rst = businessList.stream()
.collect(Collectors.maxBy(Comparator.comparing(Business::getId)));
//等价于 .max(Comparator.comparing(Business::getId));
System.out.println(rst.map(Business::getId).orElse(0L));
//输出:2
//求所有业务线的id均值
Double rst = businessList.stream()
.collect(Collectors.averagingDouble(Business::getId));
System.out.println(rst);
//输出:1.5
//根据业务线id是否大于1分块
Map> rst = businessList.stream()
.peek(business -> business.setCategoryList(null))
.collect(Collectors.partitioningBy(business -> business.getId() > 1));
System.out.println(rst);
//输出:{false=[Test.Business(id=1, name=家政, categoryList=null)], true=[Test.Business(id=2, name=速运, categoryList=null)]}
@Data
@AllArgsConstructor
static class Custom {
private long id;
private String name;
private String city;
}
public static void main(String[] args) {
List customList = Arrays.asList(
new Custom(1L, "张三", "北京"),
new Custom(2L, "李四", "北京"),
new Custom(3L, "tom", "纽约"),
new Custom(4L, "jerry", "纽约"),
new Custom(5L, "thomas", "纽约")
);
//根据城市分组
Map> rst = customList.stream()
.collect(Collectors.groupingBy(Custom::getCity));
System.out.println(rst);
}
//输出:{纽约=[Test.Custom(id=3, name=tom, city=纽约), Test.Custom(id=4, name=jerry, city=纽约), Test.Custom(id=5, name=thomas, city=纽约)], 北京=[Test.Custom(id=1, name=张三, city=北京), Test.Custom(id=2, name=李四, city=北京)]}
String rst = businessList.stream()
.map(Business::getName)
.collect(Collectors.joining(",", "[", "]"));
System.out.println(rst);
//输出:[家政,速运]
List customList = Arrays.asList(
new Custom(1L, "张三", "北京"),
new Custom(2L, "李四", "北京"),
new Custom(3L, "tom", "纽约"),
new Custom(4L, "jerry", "纽约"),
new Custom(5L, "thomas", "纽约")
);
Map> rst = customList.stream()
.collect(Collectors.groupingBy
(Custom::getCity,
Collectors.mapping(Custom::getId, Collectors.toList())));
System.out.println(rst);
//输出:{纽约=[3, 4, 5], 北京=[1, 2]}
图片.png-38.2kB
图片.png-40kB
图片.png-38.7kB
finisher.png-35.2kB
public static void main(String[] args) {
List customList = Arrays.asList(
new Custom(1L, "张三", "北京"),
new Custom(2L, "李四", "北京"),
new Custom(3L, "tom", "纽约"),
new Custom(4L, "jerry", "纽约"),
new Custom(5L, "thomas", "纽约")
);
String rst = customList.parallelStream()
.map(Custom::getName)
.collect(new MyStrCollector());
System.out.println(rst);
//输出:[张三,李四,tom,jerry,thomas]
}
//泛型含义:<待收集元素的类型,累加器的类型,最终结果的类型>
static class MyStrCollector implements Collector {
private final String prefix = "[";
private final String separator = ",";
private final String suffix = "]";
@Override
public Supplier supplier() {
return StringBuilder::new;
}
@Override
public BiConsumer accumulator() {
return (stringBuilder, item) -> {
stringBuilder.append(separator).append(item);
};
}
@Override
public BinaryOperator combiner() {
return StringBuilder::append;
}
@Override
public Function finisher() {
return (stringBuilder -> prefix + stringBuilder.toString().substring(1) + suffix);
}
@Override
public Set characteristics() {
return Collections.emptySet();
}
}
end
作者:灵派coder
链接:https://www.jianshu.com/p/e0816e6564af
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。