java8 流式开发
创建流的方式
//方式一:Stream stream = Stream.of("6","5","3","8","32")直接有.of方法创建一个可变长参数的流
Stream stream = Stream.of("6","5","3","8","32");
//方式二:Stream stream1 = Stream.empty() 直接创建一个空的流
Stream stream1 = Stream.empty();
//方式三:Stream stream2 = Arrays.stream(srt),有数组创建流
String[] srt = {"6","5","3","8","32"};
Stream stream2 = Arrays.stream(srt);
//方式四:通过文件创建流
Stream<String> stream3 = Files.lines(Paths.get("c:/tes/test.txtt"), Charset.defaultCharset());
// 方式五:通过迭代器iteartor创建流
Stream.iterate(0, n -> n + 2).limit(51).forEach(System.out::println);
// 方式六:通过generate来创建流,iteartor,generate这两个方法生成的流都是无限流,没有固定大小,可以无穷的计算下去,在上面的代码中我们使用了limit()来避免打印无穷个值。
Stream.generate(() -> "Hello Man!").limit(10).forEach(System.out::println);
//方式七 直接将集合转化成流 也是最常用的
List<String> list = new ArrayList<>();
list.stream().forEach(s -> System.out.println(s));
module
public class Student {
/** 学号 */
private long id;
private String name;
private int age;
private BigDecimal money;
/** 年级 */
private int grade;
/** 专业 */
private String major;
/** 学校 */
private String school;
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public Student(long id, String name, int age, int grade, String major, String school,BigDecimal money) {
this.id = id;
this.name = name;
this.age = age;
this.grade = grade;
this.major = major;
this.school = school;
this.money = money;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", money=" + money +
", grade=" + grade +
", major='" + major + '\'' +
", school='" + school + '\'' +
'}';
}
// 省略getter和setter
}
}
数据准备
import com.example.javademo.pojo.Student;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class DataUtils {
public static List<Student> getData(){
Student student = new Student(20163001, "丁奉", 24, 5, "土木工程", "南京大学",new BigDecimal(20));
List<Student> students = new ArrayList<Student>() {
{
add(new Student(20160001, "孔明", 20, 1, "土木工程", "武汉大学",new BigDecimal(1)));
add(new Student(20160002, "伯约", 20, 2, "信息安全", "武汉大学",new BigDecimal(1)));
add(new Student(20160003, "玄德", 22, 3, "经济管理", "武汉大学",new BigDecimal(1)));
add(new Student(20160004, "云长", 21, 1, "信息安全", "武汉大学",new BigDecimal(1)));
add(new Student(20161001, "翼德", 21, 2, "机械与自动化", "华中科技大学",new BigDecimal(1)));
add(new Student(20161002, "元直", 23, 4, "土木工程", "华中科技大学",new BigDecimal(1)));
add(new Student(20161003, "奉孝", 23, 4, "计算机科学", "华中科技大学",new BigDecimal(1)));
add(new Student(20162001, "仲谋", 22, 3, "土木工程", "浙江大学",new BigDecimal(1)));
add(new Student(20162002, "鲁肃", 23, 4, "计算机科学", "浙江大学",new BigDecimal(1)));
add(new Student(20163001, "丁奉", 24, 5, "土木工程", "南京大学",new BigDecimal(1)));
add(new Student(20163001, "丁奉", 24, 5, "土木工程", "南京大学",new BigDecimal(1)));
}
};
return students;
}
}
使用的方法
@Test
public void constructionTest(){
}
@Test
public void filter(){
//找出武汉大学的玄德
List<Student> list = DataUtils.getData().stream()
.filter(student -> "武汉大学".equals(student.getSchool())&&"玄德".equals(student.getName()))
.collect(Collectors.toList());
list.forEach(System.out::println);
}
@Test
public void distinct(){
//找出年龄是偶数的学生并且去重
DataUtils.getData().stream()
.filter(student -> student.getAge()%2==0)
.distinct().collect(Collectors.toList()).forEach(System.out::println);
}
/**
* 根据对象的某个属性去重
*/
@Test
public void distinceByProperty(){
List<Student> list = DataUtils.getData().stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() ->new TreeSet<>(Comparator.comparing(Student::getName))),ArrayList::new
));
list.forEach(System.out::println);
}
@Test
public void limit(){
//找出年龄是偶数的学生只展示前两个
DataUtils.getData().stream()
.filter(student -> student.getAge()%2==0)
//.limit(2)
//升序
.sorted(Comparator.comparing(Student::getAge))
//降序
//.sorted((x,y)->y.getAge()-x.getAge())
.collect(Collectors.toList()).forEach(student -> {
System.out.println(student);
});
}
@Test
public void sorted(){
//找出年龄是偶数的学生并且按照年纪排序降序只展示前两个
DataUtils.getData().stream()
.filter(student -> student.getAge()%2==0)
//排序,sorted里面是定义一个比较器
.sorted((s1,s2)->s2.getGrade()-s1.getGrade())
.limit(2)
.distinct().collect(Collectors.toList()).forEach(System.out::println);
}
@Test
public void skip(){
//找出年龄是偶数的学生并且按照年纪排序降序前面两个不展示
DataUtils.getData().stream()
.filter(student -> student.getAge()%2==0)
.sorted((s1,s2)->s2.getGrade()-s1.getGrade())
.skip(2)
.collect(Collectors.toList()).forEach(System.out::println);
}
@Test
public void map(){
//找出是计算机科学专业所有人的姓名
DataUtils.getData().stream()
.filter(student -> student.getMajor().equals("计算机科学"))
.map(Student::getName)
.collect(Collectors.toList()).forEach(System.out::println);
}
@Test
public void mapToInt(){
//找出是计算机科学专业的学生的年龄之和
System.out.println(DataUtils.getData().stream()
.filter(student -> student.getMajor().equals("计算机科学"))
.mapToInt(Student::getAge)
.sum());
}
@Test
public void flatMap(){
String[] strs = {"java8", "is", "easy", "to", "use"};
List<String> distinctStrs = Arrays.stream(strs)
.map(str -> str.split("")) // 映射成为Stream<String[]>
.flatMap(Arrays::stream) // 扁平化为Stream<String>
.distinct()
.collect(Collectors.toList());
distinctStrs.forEach(System.out::println);
}
@Test
public void allMatch(){
//检查是否所有的学生年龄都大于20岁
System.out.println(DataUtils.getData().stream().allMatch(student -> student.getAge() > 20));
}
@Test
public void anyMatch(){
//检查是否有来自武汉大学的学生
System.out.println(DataUtils.getData().stream().anyMatch(student -> "武汉大学".equals(student.getSchool())));
}
@Test
public void noneMathch(){
//检查是否不存在计算机科学专业的学生
System.out.println(DataUtils.getData().stream().noneMatch(student ->"计算机科学".equals(student.getMajor())));
}
@Test
public void findFirst(){
//返回满足条件的第一个
System.out.println(DataUtils.getData().stream().filter(student -> "武汉大学".equals(student.getSchool())).findFirst().get());
}
@Test
public void findAny(){
//返回满足条件的第一个,在顺序流中返回的对象和findFirst的是一样的
System.out.println(DataUtils.getData().stream().filter(student -> "武汉大学".equals(student.getSchool())).findAny().get());
}
@Test
public void reduce(){
// 归约操作
int totalAge = DataUtils.getData().stream()
.filter(student -> "计算机科学".equals(student.getMajor()))
.map(Student::getAge)
//统计年龄之和:reduce归约,里面两个参数相加,第一个是初始值
.reduce(0, (a, b) -> a + b);
//若没有初始值可以省略简写成下面的形式,但是得到的是一个optional对象,需要获取里面的值用get
//.reduce(Integer::sum).get();
System.out.println(totalAge);
}
@Test
public void count (){
//有多少学生
System.out.println(DataUtils.getData().stream().count());
}
@Test
public void maxAndMinAndAvg (){
//年龄最大的学生,注意这里得到的是Optional对象,如果需要获取里面的值需要isPresent(),为true 在get值
Optional<Student> max = DataUtils.getData().stream().max(Comparator.comparing(Student::getAge));
System.out.println(DataUtils.getData().stream().max(Comparator.comparing(Student::getAge)));
//年龄最小的学生
System.out.println(DataUtils.getData().stream().min(Comparator.comparing(Student::getAge)));
//对所有学生的年龄求总和
System.out.println((Integer) DataUtils.getData().stream().mapToInt(Student::getAge).sum());
//对所有的学生的年龄求平均值..对应的还有averagingLong、averagingDouble。
System.out.println(DataUtils.getData().stream().collect(Collectors.averagingInt(Student::getAge)));
//求出最大,最小,平均,总和
System.out.println(DataUtils.getData().stream().collect(Collectors.summarizingInt(Student::getAge)));
}
@Test
public void joining (){
//字符串拼接
System.out.println(DataUtils.getData().stream().map(Student::getName).collect(Collectors.joining(",","[","]")));
//直接转成set集合跟上面不一样,上面是一个String 而这个是一个set集合
System.out.println(DataUtils.getData().stream().map(Student::getName).collect(Collectors.toSet()));
}
@Test
public void groupingBy (){
//可以进行一级分组
Map<String, List<Student>> groups = DataUtils.getData().stream().collect(Collectors.groupingBy(Student::getSchool));
System.out.println(groups);
System.out.println("###############################");
//进行三级分组
Map<String, Map<String, Map<Integer, List<Student>>>> groups2 = DataUtils.getData().stream().collect(
Collectors.groupingBy(Student::getSchool, // 一级分组,按学校
Collectors.groupingBy(Student::getMajor, // 二级分组,按专业
Collectors.groupingBy(Student::getGrade)))); //三级分组
groups.forEach((s, students) -> System.out.println(s+":"+students));
groups2.forEach((s, students) -> System.out.println(s+":"+students));
//实际上在groupingBy的第二个参数不是只能传递groupingBy,还可以传递任意Collector类型,比如我们可以传递一个Collector.counting,用以统计每个组的个数:
System.out.println("--------------------------------------------------------------------");
//统计每个学校的每个专业有多少学生
Map<String,Map<String,Long>> mapMap = DataUtils.getData().stream().collect(Collectors.groupingBy(Student::getSchool,
Collectors.groupingBy(Student::getMajor,Collectors.counting())));
mapMap.forEach((s, stringLongMap) -> System.out.println(s+":"+stringLongMap));
}
@Test
public void partitioningBy (){
//分区,将学生分成武汉大学和非武汉大学的
Map<Boolean,List<Student>> map = DataUtils.getData().stream().collect(Collectors.partitioningBy(student->"武汉大学".equals(student.getSchool())));
map.forEach((aBoolean, students) -> System.out.println(aBoolean+":"+students));
}
/**
* 并行流式数据处理
*
* 流式处理中的很多都适合采用 分而治之 的思想,从而在处理集合较大时,极大的提高代码的性能,java8的设计者也看到了这一点,所以提供了 并行流式处理。
* 上面的例子中我们都是调用stream()方法来启动流式处理,java8还提供了parallelStream()来启动并行流式处理,parallelStream()本质上基于java7的Fork-Join框架实现,
* 其默认的线程数为宿主机的内核数。
*
* 启动并行流式处理虽然简单,只需要将stream()替换成parallelStream()即可,但既然是并行,就会涉及到多线程安全问题,
* 所以在启用之前要先确认并行是否值得(并行的效率不一定高于顺序执行),另外就是要保证线程安全。此两项无法保证,
* 那么并行毫无意义,毕竟结果比速度更加重要,以后有时间再来详细分析一下并行流式数据处理的具体实现和最佳实践。
*/
}