作者:一杯甜酒 原文:https://blog.csdn.net/u012562943/article/details/81775926
传统的数据处理都是用循环来解决,而不是像搜索数据库那样有具体的搜索语句,而Java8的Stream提供了很好的方案,往往一行就搞定了,而且Stream还可以链式操作,一行代码实现多个循环的功能,代码风格十分像nosql数据库。
但是在实际应用中发现一个巨大的问题,就是执行耗时特别长,时间开销是传统方法的几百倍,这是一个巨大的问题。
Java8可以像操作数据库一样操作内存,而且在Stream操作中对内存的开销十分友善,操作方式十分灵活,减少了IO的支出。
package com.zhy.demo.javase.java8.stream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* @ClassName User
* @Description (User类用来代表用户,里面有姓名年龄密码等常用字段)
* @author ZHY
* @date 2018年8月15日 下午11:15:26
* @Copyright © 2018【www.zhy.com Inc. All rights reserved.】
*/
public class User implements Comparable<User> {
/**
* 年龄
*/
private int age;
/**
* 姓名
*/
private String name;
/**
* 密码
*/
private String password;
/**
* 性别,0未知,1男,2女
*/
private short gendar;
/**
* 是否已婚
*/
private boolean hasMarried;
public User() {
super();
}
public User(int age, String name, String password, short gendar, boolean hasMarried) {
super();
this.age = age;
this.name = name;
this.password = password;
this.gendar = gendar;
this.hasMarried = hasMarried;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public short getGendar() {
return gendar;
}
public void setGendar(short gendar) {
this.gendar = gendar;
}
public boolean isHasMarried() {
return hasMarried;
}
public void setHasMarried(boolean hasMarried) {
this.hasMarried = hasMarried;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + ", password=" + password + ", gendar=" + gendar + ", hasMarried="
+ hasMarried + "]";
}
/**
* (重写对象是否重复方法)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof User)) {
return false;
}
User u = (User) obj;
if (age != u.age || gendar != u.gendar || hasMarried != u.hasMarried || !name.equals(u.name)
|| !password.equals(u.getPassword())) {
return false;
}
return true;
}
/**
* (Stream去重有一个先决条件,就是要去重的对象必须实现comparable接口,不能使用比较器)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(User o2) {
// 首先比较年龄大小,因为年龄的区分度比较高
User o1 = this;
if (o1.age > o2.age) {
return 1;
}
if (o1.age < o2.age) {
return -1;
}
// 如果年龄相同就比较性别,女的排在前面
if (o1.gendar > o2.gendar) {
return 1;
}
if (o1.gendar < o2.gendar) {
return -1;
}
// 如果性别也一样就比较是否已婚
if (o1.hasMarried == true && o2.hasMarried == false) {
// 结婚的排在前面
return 1;
}
if (o1.hasMarried == false && o2.hasMarried == true) {
// 结婚的排在前面
return 1;
}
// 最后比较姓名,因为字符串比较耗时较长
if (o1.name.hashCode() > o2.name.hashCode()) {
return 1;
}
if (o1.name.hashCode() < o2.name.hashCode()) {
return -1;
}
return 0;
}
public List<User> createUserDatas() {
ArrayList<User> userList = new ArrayList<>();
userList.add(new User(22, "王旭", "123456", (short) 1, true));
userList.add(new User(22, "王旭", "123456", (short) 1, true));
userList.add(new User(22, "王旭", "123456", (short) 1, true));
userList.add(new User(21, "孙萍", "a123456", (short) 2, false));
userList.add(new User(23, "步传宇", "b123456", (short) 1, false));
userList.add(new User(18, "蔡明浩", "c123456", (short) 1, true));
userList.add(new User(17, "郭林杰", "d123456", (short) 1, false));
userList.add(new User(5, "韩凯", "e123456", (short) 1, true));
userList.add(new User(22, "韩天琪", "f123456", (short) 2, false));
userList.add(new User(21, "郝玮", "g123456", (short) 2, false));
userList.add(new User(19, "胡亚强", "h123456", (short) 1, false));
userList.add(new User(14, "季恺", "i123456", (short) 1, false));
userList.add(new User(17, "荆帅", "j123456", (short) 1, true));
userList.add(new User(16, "姜有琪", "k123456", (short) 1, false));
return userList;
}
/**
* 按照年龄大小进行排序,设计一个Comparator
*
* @return
*/
public Comparator<User> getAgeComparator() {
return new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
if (o1.age > o2.age)
return 1;
if (o1.age < o2.age)
return -1;
return 0;
}
};
}
public Comparator<User> getEqualComparator() {
return new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
// 首先比较年龄大小,因为年龄的区分度比较高
if (o1.age > o2.age) {
return 1;
}
if (o1.age < o2.age) {
return -1;
}
// 如果年龄相同就比较性别,女的排在前面
if (o1.gendar > o2.gendar) {
return 1;
}
if (o1.gendar < o2.gendar) {
return -1;
}
// 如果性别也一样就比较是否已婚
if (o1.hasMarried == true && o2.hasMarried == false) {
// 结婚的排在前面
return 1;
}
if (o1.hasMarried == false && o2.hasMarried == true) {
// 结婚的排在前面
return 1;
}
// 最后比较姓名,因为字符串比较耗时较长
if (o1.name.hashCode() > o2.name.hashCode()) {
return 1;
}
if (o1.name.hashCode() < o2.name.hashCode()) {
return -1;
}
return 0;
}
};
}
}
package com.zhy.demo.javase.java8.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
/**
* @ClassName StreamStudy
* @Description (Java8 Stream操作总结)
* @author ZHY
* @date 2018年8月15日 下午11:17:27
* @Copyright © 2018【www.zhy.com Inc. All rights reserved.】
*/
public class StreamTest {
private static final Logger LOGGER = LoggerFactory.getLogger(StreamTest.class);
private static User user = new User();
/**
* 对用户按年龄进行排序
*/
@Test
public void testSort1() {
// 传统方式排序
LOGGER.info("===============传统方式排序===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
Collections.sort(userList1, user.getAgeComparator());
LOGGER.info("传统方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
userList1.stream().forEach(user -> {
LOGGER.info(user.toString());
});
// Java8的方式排序
LOGGER.info("==============Java8的方式排序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
List<User> sortedUsers = userList2.stream().sorted(user.getAgeComparator()).collect(Collectors.toList());
LOGGER.info("Java8的方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
sortedUsers.stream().forEach(user -> {
LOGGER.info(user.toString());
});
}
/**
* 选出年龄最小的三个人
*/
@Test
public void testSort2() {
// 传统方式排序
LOGGER.info("===============传统方式排序===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
Collections.sort(userList1, user.getAgeComparator());
// 切割出0,1,2这三个子元素
List<User> userListTopThree1 = userList1.subList(0, 3);
LOGGER.info("传统方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
userListTopThree1.stream().forEach(user -> {
LOGGER.info(user.toString());
});
// Java8的方式排序
LOGGER.info("==============Java8的方式排序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
List<User> userListTopThree2 = userList2.stream().sorted(user.getAgeComparator()).limit(3)
.collect(Collectors.toList());
LOGGER.info("Java8的方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
userListTopThree2.stream().forEach(user -> {
LOGGER.info(user.toString());
});
}
/**
* 去除重复数据
*/
@Test
public void testDisdinct() {
// 传统方式去重
LOGGER.info("===============传统方式去重===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
int length = userList1.size();
for (int i = 1; i < length; i++) {
if (userList1.get(i).equals(userList1.get(i - 1))) {
userList1.remove(i);
i--;
length--;
}
}
LOGGER.info("传统方式去重耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
userList1.stream().forEach(user -> {
LOGGER.info(user.toString());
});
// Java8的方式去重
LOGGER.info("==============Java8的方式去重=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
List<User> distinctUserList = userList2.stream().sorted().distinct().collect(Collectors.toList());
LOGGER.info("Java8的方式去重耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
distinctUserList.stream().forEach(user -> {
LOGGER.info(user.toString());
});
}
/**
* 按条件筛选
*/
@Test
public void testFilter() {
// 传统方式按条件筛选
LOGGER.info("===============传统方式按条件筛选===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
ArrayList<User> result1 = new ArrayList<>();
for (User user : userList1) {
if (user.getName().startsWith("韩"))
result1.add(user);
}
LOGGER.info("传统方式按条件筛选耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
result1.stream().forEach(user -> {
LOGGER.info(user.toString());
});
// Java8的方式按条件筛选
LOGGER.info("==============Java8的方式按条件筛选=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
List<User> result2 = userList2.stream().filter(user -> user.getName().startsWith("韩"))
.collect(Collectors.toList());
LOGGER.info("Java8的方式按条件筛选耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
result2.stream().forEach(user -> {
LOGGER.info(user.toString());
});
List<User> result3 = userList2.stream().filter(user -> user.getName().startsWith("韩") && user.getGendar() == 2)
.collect(Collectors.toList());
List<User> result4 = userList2.stream().filter(user -> user.getName().startsWith("韩"))
.filter(user -> user.getGendar() == 2).collect(Collectors.toList());
List<User> result5 = userList2.stream().filter(user -> user.getGendar() == 2)
.filter(user -> user.getName().startsWith("韩")).collect(Collectors.toList());
LOGGER.info("result3 ==> {}", JSON.toJSONString(result3, true));
LOGGER.info("result4 ==> {}", JSON.toJSONString(result4, true));
LOGGER.info("result5 ==> {}", JSON.toJSONString(result5, true));
}
/**
* 只列出所有人的名字和婚姻状况
*/
@Test
public void testMap() {
// 传统方式
LOGGER.info("===============传统方式===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
ArrayList<String> result1 = new ArrayList<String>();
for (User user : userList1) {
result1.add(user.getName() + ":".concat(user.isHasMarried() ? "已婚" : "未婚"));
}
LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
result1.stream().forEach(user -> {
LOGGER.info(user.toString());
});
// Java8的方式
LOGGER.info("==============Java8的方式序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
List<String> result2 = userList2.stream()
.map(user -> user.getName() + ":".concat(user.isHasMarried() ? "已婚" : "未婚"))
.collect(Collectors.toList());
LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
result2.stream().forEach(user -> {
LOGGER.info(user.toString());
});
}
/**
* 判断当前数组是否包含某些特定元素
*/
@Test
public void testAnyMatch() {
// 传统方式
LOGGER.info("===============传统方式===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
boolean isChild1 = false;
for (User user : userList1) {
if (user.getAge() < 18) {
isChild1 = true;
break;
}
}
LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
LOGGER.info("isChild1 ==> {}", isChild1);
// Java8的方式
LOGGER.info("==============Java8的方式序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
boolean isChild2 = userList2.stream().anyMatch(user -> user.getAge() < 18);
LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
LOGGER.info("isChild2 ==> {}", isChild2);
}
/**
* 确认所有元素均满足某一条件
*/
@Test
public void testAllMatch() {
// 传统方式
LOGGER.info("===============传统方式===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
boolean allMarried1 = true;
for (User user : userList1) {
if (!user.isHasMarried()) {
allMarried1 = false;
break;
}
}
LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
LOGGER.info("allMarried1 ==> {}", allMarried1);
// Java8的方式
LOGGER.info("==============Java8的方式序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
boolean allMarried2 = userList2.stream().allMatch(user -> user.isHasMarried());
LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
LOGGER.info("allMarried2 ==> {}", allMarried2);
}
/**
* 求和求平均值
*/
@Test
public void testSum() {
// 传统方式
LOGGER.info("===============传统方式===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
int sum1 = 0;
for (User user : userList1) {
sum1 += user.getAge();
}
LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
LOGGER.info("sum ==> {}", sum1);
// Java8的方式
LOGGER.info("==============Java8的方式序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
int sum2 = userList2.stream().mapToInt(user -> user.getAge()).sum();
LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
LOGGER.info("sum2 ==> {}", sum2);
}
/**
* 分组
*/
@Test
public void testGroupingBy() {
// 传统方式
LOGGER.info("===============传统方式===============");
List<User> userList1 = user.createUserDatas();
long time1 = System.currentTimeMillis();
Map<Integer, List<User>> group1 = new HashMap<>();
for (User user : userList1) {
List<User> list = group1.get(user.getAge());
if (list == null) {
list = new ArrayList<User>();
group1.put(user.getAge(), list);
}
list.add(user);
}
LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
LOGGER.info("group1 ==> {}", JSON.toJSONString(group1), true);
// Java8的方式
LOGGER.info("==============Java8的方式序=============");
List<User> userList2 = user.createUserDatas();
long time2 = System.currentTimeMillis();
Map<Integer, List<User>> group2 = userList2.stream().collect(Collectors.groupingBy(t -> t.getAge()));
// 如果想按是否结婚分组,也就是key变成bool,那就应该这么写
// Map<Boolean,List<User>> group =
// users.stream().collect(Collectors.partitioningBy(t->t.hasMarried));
LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
LOGGER.info("group2 ==> {}", JSON.toJSONString(group2), true);
}
/**
* 链式操作
*/
@Test
public void testLinkOperation() {
LOGGER.info("==============Java8链式操作=============");
List<User> userList = user.createUserDatas();
long time = System.currentTimeMillis();
userList.stream().filter(t -> t.getGendar() == 2).map(t -> t.getName()).forEach(System.out::println);
LOGGER.info("Java8链式操作耗时 ==> {} (ms)", System.currentTimeMillis() - time);
}
}
大家最好把上面代码复制到便一起上试试!!!