这是我工作中用的比较多的stream流操作,欢迎更多伙伴一起补充常用的操作,后续还会更新。
实体类:Device.java
package com.attack.bat.interview.java8.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.Temporal;
/**
* @Auther: MoXi
* @Date: 2021/05/23/11:11
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Device {
private String deviceId;
private String parentId;
private String deviceName;
private String deviceAge;
private Integer anInteger;
private Double aDouble;
private int anInt;
private BigDecimal bigDecimal;
private LocalDateTime createTime;
private LocalDateTime receivedTime;
}
具体操作:Jdk8StreamApi.java
package com.attack.bat.interview.java8.stream;
import com.attack.bat.interview.java8.entity.Device;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* @Auther: MoXi
* @Date: 2021/05/23/11:10
* @Description:
*/
public class Jdk8StreamApi {
public static void main(String[] args) {
Device apple = new Device("1", "100", "Apple", "24", 12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
Device apple2 = new Device("1.5", "100", "Apple2", "24", 12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
// Device apple3 = new Device("1.5", "100", "Apple2", "24",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
Device huaWei = new Device("2", "200", "HuaWei", "25",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
Device xiaoMi = new Device("3", "300", "XiaoMi", "28",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
Device vivo = new Device("4", "400", "Vivo", "27",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
Device oppo = new Device("5", "500", "Oppo", "28",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
List<Device> devices = Arrays.asList(
apple,huaWei,xiaoMi,vivo,oppo,apple2/*,apple3*/
);
ArrayList<Device> list = new ArrayList<>();
list.add(apple);
list.add(apple2);
// list.add(apple3);
list.add(huaWei);
list.add(xiaoMi);
list.add(vivo);
list.add(oppo);
//1、把集合的其中一个属性收集成List
List<String> parentIds = devices.stream().map(Device::getParentId).collect(Collectors.toList());
System.out.println("parentIds = " + parentIds);
parentIds.forEach(System.out::println);
System.out.println("============================================");
//2、把集合收集成一个Map,自己指定键和值,这里指定的键不唯一会有异常 Duplicate key Apple2
Map<String, String> idName = devices.stream().collect(Collectors.toMap(Device::getDeviceId, Device::getDeviceName));
System.out.println("============================================");
//3、把集合中包含某个属性的对象收集成list
List<Device> devicesCollect = devices.stream().filter(device -> parentIds.contains(device.getParentId())).collect(Collectors.toList());
devicesCollect.forEach(System.out::println);
System.out.println("============================================");
//4、将字符串分割成Integer类型的list
String iSlitYou = "520,1314,521,1413";
List<Integer> collect = Stream.of(iSlitYou.split(",")).map(Integer::valueOf).collect(Collectors.toList());
System.out.println("collect = " + collect);
System.out.println("============================================");
//5、peek和map类似,peek的入参是consumer消费型没有返回值,map有返回值,peek适合元素的中间操作,map方法的入参为function比peek多了一个return
Device device1 = new Device("100","100","helloworld","100",12,13D,14,new BigDecimal("100"), LocalDateTime.now(), LocalDateTime.now().minusDays(1L));
List<Device> collect1 = list.stream().filter(action -> device1.getParentId().equals(action.getParentId())).peek(action -> action.setDeviceAge(device1.getDeviceAge())).peek(System.out::println).collect(Collectors.toList());
System.out.println("collect1 = " + collect1);
System.out.println("list = " + list);
System.out.println("============================================");
//6、通过找出list中属性最大的值对象,有多个会选择比较靠前的,注意这里Device::getDeviceAge是string类型的所以28比100还大,所以改写一下
// Device max = list.stream().max(Comparator.comparing(Device::getDeviceAge)).get();
Device max = list.stream().max(Comparator.comparing(Device::getDeviceAge,(s1,s2) -> {
Integer s1Int = Integer.valueOf(s1);
Integer s2Int = Integer.valueOf(s2);
return s1Int.compareTo(s2Int);
})).get();
Device min = list.stream().min(Comparator.comparing(Device::getDeviceAge,(s1,s2) -> {
Integer s1Int = Integer.valueOf(s1);
Integer s2Int = Integer.valueOf(s2);
return s1Int.compareTo(s2Int);
})).get();
System.out.println("max = " + max);
System.out.println("min = " + min);
System.out.println("============================================");
//7、通过list中的某个属性进行排序
List<Device> collect2 = list.stream().sorted(Comparator.comparing(Device::getDeviceAge, (s1,s2) -> {
Integer s1Int = Integer.valueOf(s1);
Integer s2Int = Integer.valueOf(s2);
return s1Int.compareTo(s2Int);
})).peek(System.out::println).collect(Collectors.toList());
System.out.println("collect2 = " + collect2);
System.out.println("============================================");
//8、IntStream.rangeClosed()产生指定区间的有序IntStream,与IntStream.range()不同的是,产生的元素包含最后一个,即左闭右闭。
//IntStream是存的是int类型的stream,而Steam是一个存了Integer的stream。boxed的作用就是将int类型的stream转成了Integer类型的Stream。
IntStream intStream = IntStream.rangeClosed(0, 5);
System.out.println("intStream = " + intStream);
List<Integer> integers = intStream.boxed().collect(Collectors.toList());
System.out.println("integers = " + integers);
//这里发现int不能放入list,Java集合不能存放基本数据类型,只能存放对象的引用。
//每个集合元素都是一个引用变量,实际内容都存放在堆内或方法区里面
//但是基本数据类型是在栈内存上分配空间的,栈上的数据随时会被收回。
// ArrayList<Integer> ints = new ArrayList<int>();
List<Device> collect3 = IntStream.rangeClosed(0,5).boxed().collect(Collectors.toList()).stream().map(number -> {
Device device = new Device();
device.setDeviceName(String.valueOf(number));
System.out.println("number = " + number);
return device;
}).collect(Collectors.toList());
System.out.println("collect3 = " + collect3);
//reduce求和,这里Device::getDeviceId是字符串,所以使用Double::new转换了一下
Double reduce = list.stream().map(Device::getDeviceId).map(Double::new).reduce(0D, Double::sum);
System.out.println("reduce = " + reduce);
int sum = list.stream().mapToInt(Device::getAnInt).sum();
System.out.println("sum = " + sum);
int sum1 = list.stream().mapToInt(Device::getAnInteger).sum();
System.out.println("sum1 = " + sum1);
double sum2 = list.stream().mapToDouble(Device::getADouble).sum();
System.out.println("sum2 = " + sum2);
BigDecimal reduce1 = list.stream().map(Device::getBigDecimal).reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("reduce1 = " + reduce1);
//9、ChronoUnit.MINUTES.between(),很少用到
Long reduce2 = list.stream().map(device -> ChronoUnit.MINUTES.between(device.getCreateTime(), device.getReceivedTime())).reduce(0L, Long::sum);
System.out.println("reduce2 = " + reduce2);
//10.groupingBy进行分组,以指定的属性作为key,同一组的添加到list
Map<String, List<Device>> collect4 = list.stream().collect(Collectors.groupingBy(Device::getParentId));
collect4.forEach((s,v) ->{
System.out.println("s = " + s);
System.out.println("v = " + v);
});
//11.自定义根据某个属性去重
List<Device> distinctList = list.stream().filter(distinctByName(item -> item.getDeviceId())).collect(Collectors.toList());
distinctList.forEach(System.out::println);
//顺便复习一下map的遍历方式
Set<String> keys = idName.keySet();
//效率较高,较清晰
for (String key : keys) {
System.out.println("key = " + key);
}
for (String value : idName.values()) {
System.out.println("value = " + value);
}
//比较方便,用的比较多
Set<Map.Entry<String, String>> entries = idName.entrySet();
System.out.println("entries = " + entries);
for (Map.Entry<String, String> entry : entries) {
System.out.println("entry.getKey() = " + entry.getKey());
System.out.println("entry.getValue() = " + entry.getValue());
}
//用的也不少
idName.forEach((s, s2) -> {
System.out.println("s = " + s);
System.out.println("s2 = " + s2);
});
//迭代器
Iterator<Map.Entry<String, String>> iterator = idName.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String, String> next = iterator.next();
System.out.println("next.getKey() = " + next.getKey());
System.out.println("next.getValue() = " + next.getValue());
}
//notes:在遍历过程中进行remove操作,只能用iterator遍历方式,其他的会抛出异常UnsupportedOperationException,list也是如此
for (Device device : devices) {
devices.remove(device);
}
//正确的遍历删除方式
Iterator<Device> it = list.iterator();
System.out.println("list = " + list);
while (it.hasNext()){
it.next();
it.remove();
}
Collections.addAll(list,apple,huaWei,xiaoMi,vivo,oppo);
//由于每次删除元素总会向前移动,所以从后面删除就不会出现那样的问题
for (int i = list.size() - 1; i >= 0; i--){
System.out.println("list.get(i) = " + list.get(i));
list.remove(list.get(i));
}
//根据中间值判断再执行i++
for (int i = 0; i < list.size(); i++) {
System.out.println("list.get(i) = " + list.get(i));
if (list.size() / 2 == i){
list.remove(i);
i--;
}
}
}
/**
* Stream根据自定义属性去重
* @param keyExtractor
* @param <T>
* @return
*/
private static <T> Predicate<T> distinctByName(Function<? super T , Object> keyExtractor){
Map<Object , Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}