个人博客 个人博客

2020 记录精彩的程序人生

目录
Java8 lambda表达式 stream基础
/  

Java8 lambda表达式 stream基础 置顶!

Stream操作

常见的操作可以归类如下:
Intermediate:中间操作
map、flatMap、filter、distinct、sorted、peek、limit、 skip、 parallel、 sequential、 unordered

Terminal: 最终操作
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

Short-circuiting: 短路操作
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

初始值

省实体类、城市实体类、地区实体类

// 地区
List<RegionChild> regionChilds1 = new ArrayList<RegionChild>();
RegionChild r1 = new RegionChild("10001", "福田区", 1501700);
RegionChild r2 = new RegionChild("10002", "南山区", 1356300);
RegionChild r3 = new RegionChild("10003", "南山区", 1356300); 
regionChilds1.add(r1);
regionChilds1.add(r2);
regionChilds1.add(r3);
		
List<RegionChild> regionChilds2 = new ArrayList<RegionChild>();
RegionChild r4 = new RegionChild("10001", "越秀区", 1163800);
RegionChild r5 = new RegionChild("10002", "天河区", 1697900);
RegionChild r6 = new RegionChild("10003", "增城区", 1413000);
regionChilds2.add(r4);
regionChilds2.add(r5);
regionChilds2.add(r6);

// 城市
List<CityChild> cityChilds = new ArrayList<CityChild>();
CityChild c1 = new CityChild(1, "1001", "深圳市", regionChilds1);
CityChild c2 = new CityChild(2, "1002", "广州市", regionChilds2);
cityChilds.add(c1);
cityChilds.add(c2);
// 省
ProvinceParent provinceParent = new ProvinceParent(1, "100", "广东省", cityChilds);

遍历forEach

// 利用forEach遍历 getCityChilds
provinceParent.getCityChilds().forEach(city-System.out.println(city.getCityNo()+city.getCityName()));

运行结果:

1001深圳市
1002广州市

从一个List集合中筛选出符合条件的“对象”

// 在集合中找到等于"深圳市"
CityChild getCity = provinceParent.getCityChilds().stream().filter(city->city.getCityName().equals("深圳市")).findFirst().orElse(null);
System.out.println(getCity.getCityNo()+getCity.getCityName());

运行结果:

1001深圳市

从一个List集合中筛选出符合条件的“集合”

// 得到等于南山区所有的list集合
List<RegionChild> getRegionChilds = provinceParent.getCityChilds().stream()
	.flatMap(child -> child.getRegionChilds().stream())
	.filter(region -> region.getRegionName().equals("南山区")).collect(Collectors.toList());
	
getRegionChilds.forEach(region -> System.out.println(region.getRegionNo() + region.getRegionName()));

运行结果:

10002南山区
10003南山区

从一个对象中抽取该对象的某一个字段重新生成一个新的集合

//在CityChild中抽取该对象的getCityNo重新生成一个新的集合
Set<String> collect = provinceParent.getCityChilds().stream().map(CityChild::getCityNo).collect(Collectors.toSet());
		collect.forEach(region->System.out.println(region));

运行结果:

1002
1001

过滤集合中相同元素

//使用distinct关键字
List<CityChild> collect = provinceParent.getCityChilds().stream().distinct().collect(Collectors.toList());
collect.forEach(region->System.out.println(region.getCityNo()+region.getCityName()));

使用flatMap扁平化

// 遍历CityChild集合中的getRegionChilds集合,使用flatMap扁平化得到RegionChild集合
List<RegionChild> getRegionChilds = cityChilds.stream().filter(citys -> citys.getCityName().equals("深圳市"))
	.flatMap(city -> city.getRegionChilds().stream()).collect(Collectors.toList());
getRegionChilds.forEach(region -> System.out.println(region.getRegionNo() + region.getRegionName() + region.getPopulation()));

对某一个对象中的字段进行求和 / 平均值

//在region集合中的城市等于深圳市的人口,使用summingInt进行求和 及 使用averagingInt取平均值
Integer sumPop = cityChilds.stream().filter(city -> city.getCityName().equals("深圳市")).flatMap(region->region.getRegionChilds().stream()).collect(Collectors.summingInt(RegionChild::getPopulation));
System.out.println("深圳市总人口:"+sumPop);
		
Double avgPop = cityChilds.stream().filter(city -> city.getCityName().equals("深圳市")).flatMap(region->region.getRegionChilds().stream()).collect(Collectors.averagingInt(RegionChild::getPopulation));
System.out.println("深圳市平均人口:"+avgPop);

运行结果:

深圳市总人口:4214300
深圳市平均人口:1404766.6666666667

从集合中找出最大值/最小值的对象

max() / min()

//找出人口数量最大/最小的RegionChild对象
RegionChild regionMax = cityChilds.stream().flatMap(region->region.getRegionChilds().stream()).max(Comparator.comparing(RegionChild::getPopulation)).get();
System.out.println("最大值:"+regionMax.getRegionName()+"---"+regionMax.getPopulation());
		
RegionChild regionMin = cityChilds.stream().flatMap(region->region.getRegionChilds().stream()).min(Comparator.comparing(RegionChild::getPopulation)).get();
System.out.println("最小值:"+regionMin.getRegionName()+"---"+regionMin.getPopulation());

运行结果:

最大值:天河区---1697900
最小值:越秀区---1163800

根据对象中的某的字段排序,默认升序 / 降序reversed()

// 根据人口数量排序:升序 / 降序reversed()
System.out.println("升序:");
List<RegionChild> regionSX = cityChilds.stream().flatMap(region->region.getRegionChilds().stream())
	.sorted(Comparator.comparing(RegionChild::getPopulation)).collect(Collectors.toList());
regionSX.forEach(region -> System.out.println(region.getRegionNo() + region.getRegionName() + region.getPopulation()));

System.out.println("降序:");
List<RegionChild> regionJX = cityChilds.stream().flatMap(region->region.getRegionChilds().stream())
	.sorted(Comparator.comparing(RegionChild::getPopulation).reversed()).collect(Collectors.toList());
regionJX.forEach(region -> System.out.println(region.getRegionNo() + region.getRegionName() + region.getPopulation()));

运行结果:

升序:
10001越秀区1163800
10002南山区1356300
10003南山区1356300
10003增城区1413000
10001福田区1501700
10002天河区1697900
降序:
10002天河区1697900
10001福田区1501700
10003增城区1413000
10002南山区1356300
10003南山区1356300
10001越秀区1163800

使用groupingBy把相同的分成一组

// 在对象里,相同的getRegionName分成一组
List<Entry<String, List<RegionChild>>> collect = cityChilds.stream()
	.filter(city -> city.getCityName().equals("深圳市")).flatMap(region -> region.getRegionChilds().stream())
	.collect(Collectors.groupingBy(RegionChild::getRegionName)).entrySet().stream()
	.collect(Collectors.toList());
for (Entry<String, List<RegionChild>> entry : collect) {
	String key = entry.getKey();
	System.out.println(key);
	List<RegionChild> value = entry.getValue();
	value.forEach(region -> System.out.println(region.getRegionNo() + region.getRegionName()));
}

运行结果:

南山区
10002南山区
10003南山区
福田区
10001福田区

遍历某一个对象集合,将该集合中每一个对象的字段内容,赋值到一个新构建的对象中,最终结果返回新对象的集合

// 遍历ProvinceParent对象中的getCityChilds集合,将getCityChilds集合中每一个对象的字段内容,赋值到一个新构建的genCityChild对象中,最终结果返回新对象的集合
private List<CityChild> createCityChilds(ProvinceParent provinceParent){
	return provinceParent.getCityChilds().stream().map(city->genCityChild(city)).collect(Collectors.toList());
}
	
private CityChild genCityChild(CityChild cityChild) {
	CityChild city = new CityChild();
	//内容...
	return city;
}

将一个List<Object[]>转成一个list<对象>

应用场景:在sql语句只查询一个对象的某几个字段时使用

SQL语句:只查询itemNo,itemName两个字段
@Query("select i.itemNo,i.itemName from ItemMaster i where i.itemNo in :itemNos")
List<Object[]> getAllItemMasters(@Param(value = "itemNos") Set<String> itemNos);
	
Service层:
private List<ItemMaster> genItemMasters(Set<String> itemNos) {
	List<Object[]> allItemMasters = itemMasterRepository.getAllItemMasters(itemNos);
	return allItemMasters.stream().map(item -> genItemMaster(item)).collect(Collectors.toList());
}
	
private ItemMaster genItemMaster(Object[] object) {
        ItemMaster itemMaster = new ItemMaster();
        itemMaster.setItemNo(object[0].toString());
        itemMaster.setItemName(object[1].toString());
    }
    return itemMaster;
}

使用groupingBy可以进行分组求和,用来合并某些相同内容的对象

/*
因为groupingBy可以根据多个字段进行分组,但是当字段过多时,可以创建一个分组类用于分组。
使用GeneralDpPpOrderDatailGroup分组类对GeneralDpPpOrderDetail对象集合,根据分组类中构造器的字段进行分组,
分完组后是一个map<分组类,List<被分组对象>>的集合,可以再次使用.map来遍历该集合,对每组中的list集合做进一步操作
*/
public class GeneralDpPpOrderDatailGroup {
	public GeneralDpPpOrderDatailGroup(GeneralDpPpOrderDetail generalDpPpOrderDetail) {
		this.dpNo = generalDpPpOrderDetail.getdPNo();
		this.dpWidth = generalDpPpOrderDetail.getDpWidth();
		this.dpHeight = generalDpPpOrderDetail.getDpHeight();
	}    
}

private void setGeneralDpPpOrderDetail(DpOrder dpOrder,GeneralDpPpOrder generalDpPpOrder) {
	List<GeneralDpPpOrderDetail> groupedDpPpDetails = 	dpOrder.getDpOrderElements().stream()
	.map(element -> genDpPpDetailOfNoGroup(element, dpOrder.getBackPanelItemNo()))		
	.collect(Collectors.groupingBy(GeneralDpPpOrderDatailGroup::new)).entrySet().stream()
	.map(entry -> genDpPpOrderDetail(entry)).collect(Collectors.toList());
	generalDpPpOrder.setGeneralDpPpOrderDetails(groupedDpPpDetails);
}

private GeneralDpPpOrderDetail genDpPpOrderDetail(Entry<GeneralDpPpOrderDatailGroup, List<GeneralDpPpOrderDetail>> entry) {
    if (entry.getValue() != null && entry.getValue().size() > 0) {
        // 内容...
	entry.getValue().stream.filter()省略....
    }
    return null;
}