时隔多月迎来了java学习的进阶之路。本人菜鸡一枚,写的学习笔记虽力求完美,怎无奈差强人意!这里的笔记大多是拾人牙慧,还没有来自自身的经验总结。希望以后能有机会写出自己的体会。也欢迎交流学习,虽然我知道写的东西很少有人看,哈哈。
首先我们新建一个员工类
package Entity;
public class Employee {
public String name;
public String address;
public int age;
public int salary;
// 构造
public Employee(String name,String address,int salary,int age){
this.name = name;
this.address = address;
this.age = age;
this.salary = salary;
}
public Employee(){
this.name = "未知";
this.address = "未知";
this.age = 23;
this.salary = 5000;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
// 输出内容
public static void show(Employee employee){
System.out.println(employee.name+" "+employee.address+" "+employee.age+" "+employee.salary);
}
}
集合stream的简单操作如下,新建一个类:
package JDKNewFeature;
import Entity.Employee;
import java.util.Arrays;
import java.util.List;
/**
* @ClassName StreamSimple
* @Description TODO 多个中间操作可以连接起来形成一个流水线,除非流水想上出发终止操作。否则中间操作不会执行任何的处理,而在终止操作时一次性全部处理,成为“惰性求值”。
* @Date 2018/7/30 14:30
* @Version 1.0
*/
public class StreamSimple {
/** TODO
* 筛选和切片
*
* filter -- 接受Lambda,从流中排除某些元素
* limit -- 截断流,使其元素不超过某个给定数量
* skip -- 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit互补。
* distinct -- 去重,通过hashcode和equals去重。
*/
public static void main(String[] arg) {
List list = Arrays.asList(
new Employee("张三", "上海", 5000, 22),
new Employee("李四", "北京", 4000, 23),
new Employee("c五", "日本", 6000, 50),
new Employee("b七", "香港", 7000, 50),
new Employee("赵六", "纽约", 1000, 8)
);
// 操作开始了
list.stream()
.filter(e -> e.getAge() > 20)//条件过滤
.limit(4)//不多于4个
.skip(1)//跳过1个
.distinct()//去重
.forEach(e -> Employee.show(e));//遍历
}
}
这里展示一下稍微复杂一点的应用场景
package JDKNewFeature;
import Entity.Employee;
import java.util.*;
import java.util.stream.Collectors;
/**
* @ClassName StreamCollect
* @Description TODO 将流转换成其他格式,接受一个Collector接口的实现,用于给Stream中元素做汇总的操作。Collector接口中方法的实现决定了如何对流进行收集操作(如收集到List、Set、Map)中,Collectors实用类提供了很多静态方法,可以方便的创建常用收集器实例,具体方法见API
* @Date 2018/7/31 9:40
* @Version 1.0
*/
public class StreamCollect {
public static void main(String[] args){
List employees = Arrays.asList(
new Employee("张三", "上海", 5000, 22),
new Employee("李四", "北京", 4000, 23),
new Employee("c五", "日本", 6000, 50),
new Employee("b七", "香港", 7000, 50),
new Employee("赵六", "纽约", 1000, 8)
);
/**
* 收集
* collect
* -- 将流转换成其他的形式,接收一个Collector接口的实现,可以通过Collectors的实用类操作
*/
//收集姓名到列表
List collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("-------------------------");
//收集姓名到set
Set collect1 = employees.stream().map(Employee::getName)
.collect(Collectors.toSet());
collect1.forEach(System.out::println);
System.out.println("--------------------------");
//收集姓名到指定的数据结构
LinkedHashSet collect2 = employees.stream().map(Employee::getName)
.collect(Collectors.toCollection(LinkedHashSet::new));
collect2.forEach(System.out::println);
//总数
Long collect3 = employees.stream()
.collect(Collectors.counting());
System.out.println(collect3);
System.out.println("-----------总数----------------------");
//平均
Double collect4 = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(collect4);
System.out.println("------------平均-------------------");
//总和
Double collect5 = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(collect5);
System.out.println("--------总和---------------");
//最大值
Optional collect6 = employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect6.get().getSalary());
System.out.println("----------最大值-------------");
// 进阶版
System.out.println("进阶的战士");
//单级分组
Map> collect7 = employees.stream().collect(Collectors.groupingBy(Employee::getAge));
System.out.println(collect7);
System.out.println("----------------------");
// 多级分组
Map>> collect8 = employees.stream().collect(Collectors.groupingBy(Employee::getAge, Collectors.groupingBy(e -> {
if (e.getAge() < 20)
return "少年";
else if (e.getAge() < 30)
return "青年";
else
return "中年";
})));
System.out.println(collect8);
System.out.println("----------------------");
//分区--满足条件一个区,不满足另一个区
Map> collect9 = employees.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 8000));
System.out.println(collect9);
System.out.println("-----------------------");
//收集各种统计数据
DoubleSummaryStatistics collect10 = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(collect10+"-----------平均薪水"+collect10.getAverage());
//连接字符串
String collect11 = employees.stream().map(Employee::getName).collect(Collectors.joining(",", "-----", "-----"));
System.out.println(collect11);
}
}
package JDKNewFeature;
import Entity.Employee;
import java.util.Arrays;
import java.util.List;
/**
* @ClassName StreamSimpleSort
* @Description TODO
* @Date 2018/7/30 15:08
* @Version 1.0
*/
public class StreamSimpleSort {
public static void main(String[] args){
List list = Arrays.asList(
new Employee("张三", "上海", 5000, 22),
new Employee("李四", "北京", 4000, 23),
new Employee("c五", "日本", 6000, 50),
new Employee("b七", "香港", 7000, 50),
new Employee("赵六", "纽约", 1000, 8)
);
// list.stream()
// .sorted()//自然排序
// .forEach(System.out::println);
System.out.println("------------------------------");
list.stream()
.sorted((e1,e2) -> {//定制排序
if(e1.getSalary() == e2.getSalary())
return e1.getName().compareTo(e2.getName());
else
return e1.getSalary() - e2.getSalary();
}).forEach(e -> Employee.show(e));
}
}
package JDKNewFeature;
import Entity.Employee;
import java.util.Arrays;
import java.util.List;
/**
* @ClassName StreamSimpleV2
* @Description TODO
* @Date 2018/7/30 14:56
* @Version 1.0
*/
public class StreamSimpleV2 {
public static void main(String[] args){
/** TODO
* 映射
* map -- 接受Lambda,将元素转换成其他形式或提取信息,接受一个函数作为参数,
* 该函数会被应用到每个元素上,并将其映射成一个新的元素。
*
* flatmap -- 接受一个函数做为参数,将流中的每个值都转换成另一个流,然后将所有流连接成一个流,
*/
List list = Arrays.asList(
new Employee("张三", "上海", 5000, 22),
new Employee("李四", "北京", 4000, 23),
new Employee("c五", "日本", 6000, 50),
new Employee("b七", "香港", 7000, 50),
new Employee("赵六", "纽约", 1000, 8)
);
//简单操作
list.stream()
.map(e -> e.name)//中间操作 映射
.forEach(System.out::println);//终止流
}
}
package JDKNewFeature;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* @ClassName StreamSimpleV3
* @Description TODO
* @Date 2018/7/30 15:03
* @Version 1.0
*/
public class StreamSimpleV3 {
/**
* 映射
* map -- 接受Lambda,将元素转换成其他形式或提取信息,接受一个函数作为参数,
* 该函数会被应用到每个元素上,并将其映射成一个新的元素。
*
* flatmap -- 接受一个函数做为参数,将流中的每个值都转换成另一个流,然后将所有流连接成一个流,
*/
public static void main(String[] args){
List list = Arrays.asList("aaa","bbb","ccc","ddd");
Stream> streamStream = list
.stream()
.map(StreamSimpleV3::getCharacter);//流中还是流
streamStream.forEach(sm -> sm.forEach(System.out::println));
System.out.println("-------------------------------------");
list.stream()
.flatMap(StreamSimpleV3::getCharacter)//大流中直接包含的是流元素,相当于add和addAll的区别。
.forEach(System.out::println);
}
public static Stream getCharacter(String str){
List list = new ArrayList<>();
for (char c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
}
新建一个并行框架类
package JDKNewFeature;
import java.util.concurrent.RecursiveTask;
/**
* @ClassName StreamParallel
* @Description TODO Stream API 可以声明性地通过parallel() 与sequential() 在并行流与顺序流之间进行切换。 Fork/Join框架
* @Date 2018/7/31 14:48
* @Version 1.0
*/
public class StreamParallel extends RecursiveTask {
private long start;
private long end;
private static final long THRESHHOLD = 10000;
public StreamParallel(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end - start;
if(length <= THRESHHOLD){
long sum = 0;
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
}else{
long middle = (start + end) / 2;
StreamParallel left = new StreamParallel(start, middle);
left.fork();
StreamParallel right = new StreamParallel(middle + 1, end);
right.fork();
return left.join()+right.join();
}
}
}
综合比较现有的集中方式计算效率
package JDKNewFeature;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
/**
* @ClassName Tester
* @Description TODO 测试入口 JDK7的实现方式最优,stream并行流计算次之,普通的最次
* @Date 2018/7/31 14:51
* @Version 1.0
*/
public class Tester {
public static void main(String[] args){
parallelTest8();
parallelTest();
parallelTestPlain();
}
// 并行流测试函数 JDK7
public static void parallelTest(){
Instant start = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask task = new StreamParallel(0, 100000000L);
Long sum = pool.invoke(task);
Instant end = Instant.now();
System.out.println("老年的迪斯科耗时:"+Duration.between(start,end).toMillis());
}
// jdk的实现方式
private static void parallelTest8(){
Instant start = Instant.now();
long sum = LongStream.rangeClosed(0, 1000000000L)
.parallel()//并行流
// .sequential()//串行流
.reduce(0, Long::sum);
Instant end = Instant.now();
System.out.println("摇滚的迪斯科耗时:"+Duration.between(start,end).toMillis());
}
// 最普通的方式
private static void parallelTestPlain(){
Instant start = Instant.now();
Long sum = 0L;
for (int i = 0; i <= 100000000L; i++) {
sum += i;
}
Instant end = Instant.now();
System.out.println("普通的迪斯科耗时:"+Duration.between(start,end).toMillis());
}
}
package JDKNewFeature;
import Entity.Employee;
import java.util.Optional;
/**
* @ClassName OptionalSimple
* @Description TODO OptionSimple类学习
* @Date 2018/7/31 15:31
* @Version 1.0
*/
public class OptionalSimple {
/**
* 常用方法:
* Optional.of(T t) : 创建一个Optional 实例
* Optional.empty() : 创建一个空的Optional 实例
* Optional.ofNullable(T t):若t 不为null,创建Optional 实例,否则创建空实例
* isPresent() : 判断是否包含值
* orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
* orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回s 获取的值
* map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
* flatMap(Function mapper):与map 类似,要求返回值必须是Optional
*/
public static void main(String[] args) {
ofTest();
mapTest();
orElseTest();
ofnullableTest();
flatMapTest();
emptyTest();
}
//of 构建
public static void ofTest() {
Optional op = Optional.of(new Employee());
Employee employee = op.get();
Employee.show(employee);
//Optional
package JDKNewFeature;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
/**
* @ClassName PredicateSimple
* @Description TODO Interface Predicate 可以用作lambda表达式或方法引用的赋值对象
* @Date 2018/7/30 10:49
* @Version 1.0
*/
public class PredicateSimple {
public static void main(String[] args) {
System.out.println("普通战士");
String name = "";
String name1 = "12";
String name2 = "12345";
System.out.println(validInput(name, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3));
System.out.println(validInput(name1, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3));
System.out.println(validInput(name2, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3));
System.out.println("进阶战士");
// lambda
Set simple = new HashSet<>(Arrays.asList("love", "you", "like", "a song !"));
simple.stream().forEach(e -> System.out.println(validInput(e, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3)));
System.out.println("进阶战士--Equal");
simple.stream().forEach(e -> System.out.println(Predicate.isEqual("love").or(Predicate.isEqual("you")).negate().test(e)));
}
public static boolean validInput(String name, Predicate function) {
// 给定的参数上,评估谓词 !inputStr.isEmpty() && inputStr.length() <= 3
return function.test(name);
}
}
package JDKNewFeature;
import Entity.Employee;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
* @ClassName MapReduce
* @Description TODO map和reduce的连接通常称为map-reduce模式,因google用它进行网络搜索而出名
* @Date 2018/7/30 15:14
* @Version 1.0
*/
public class MapReduce {
public static void main(String[] args){
/**
* 终止操作:
*
* 归约
* reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
* -- 可以将流中的元素反复结合起来,得到一个值
*/
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(reduce);
List employees = Arrays.asList(
new Employee("张三", "上海", 5000, 22),
new Employee("李四", "北京", 4000, 23),
new Employee("c五", "日本", 6000, 50),
new Employee("b七", "香港", 7000, 50),
new Employee("赵六", "纽约", 1000, 8)
);
Optional mapreduce = employees.stream()
.map(Employee::getSalary)//现将salsry映射出来
.reduce(Integer::sum);//进行归约求和
System.out.println(mapreduce.get());
}
}
package JDKNewFeature;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @ClassName Genericty
* @Description TODO - extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类; super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object;
* @Date 2018/8/2 9:14
* @Version 1.0
*/
public class Genericty {
public static void main(String[] args){
List extends Father> list = new LinkedList();
// list.add(new Son()); 不能使用add方法
Father father = list.get(0);//读取出来的东西只能存放在Father或它的基类里。
Object object = list.get(0);//读取出来的东西只能存放在Father或它的基类里。
Human human = list.get(0);//读取出来的东西只能存放在Father或它的基类里。
Son son = (Son)list.get(0);
//super只能添加Father和Father的子类,不能添加Father的父类,读取出来的东西只能存放在Object类里
List super Father> list1 = new ArrayList<>();
list1.add(new Father());
// list1.add(new Human());//compile error
list1.add(new Son());
// Father person1 = list1.get(0);//compile error
// Son son = list1.get(0);//compile error
Object object1 = list1.get(0);
}
}
class Human {
}
class Father extends Human {
}
class Son extends Father {
}
class LeiFeng extends Father {
}