1:常用函数式接口及使用
个人对这些函数式接口的理解
上面的这些函数式接口,主要描述的是这些类型中的函数式接口,
在我们的实际应用中,我们如果用到这些类型,我们可以直接使用,
而不是说自己去定义一个这样的方法,例子如下所示:
自定义
public interface SkuPredicate {
/***
* 选择判断接口
* @param sku
* @return {@link boolean}
* @author xieyucan
* CreateDate 2022/3/10 16:00
*/
boolean test(Sku sku);
}
public class SkuBooksCategoryPredicate implements SkuPredicate{
@Override
public boolean test(Sku sku) {
return sku.getSkuCategory().equals(SkuCategoryEnum.BOOKS);
}
}
//方法调用
/**
* 根据不同的sku判断标准,对sku列表进行过滤
* @param cartSkuList
* @param predicate
* @return
*/
public List<Sku> filterSkus(List<Sku> cartSkuList, SkuPredicate predicate)
{
List<Sku> list=new ArrayList<>();
for(Sku sku:cartSkuList)
{
/**
* 根据不同的sku标准判断
*/
if(predicate.test(sku))
{
list.add(sku);
}
}
return list;
}
//Test
public class Version4Test {
public static void main(String[] args) {
CartService cartService = new CartService();
List<Sku> cartSkuList = CartService.getCartSkuList();
cartService.filterSkus(cartSkuList, (Sku sku)->sku.getTotalPrice()>2000).forEach(System.out::println);
}
}
//结果:
Sku{skuId=654032, skuName='无人机', skuPrice=4999.0, totalNum=1, totalPrice=4999.0, skuCategory=ELECTRONICS}
Sku{skuId=642934, skuName='VR-一体机', skuPrice=2299.0, totalNum=1, totalPrice=2299.0, skuCategory=ELECTRONICS}
Sku{skuId=675489, skuName='跑步机', skuPrice=2699.0, totalNum=1, totalPrice=2699.0, skuCategory=SPORTS}
调用函数式接口
//方法调用
public List<Sku> filterSkus(List<Sku> cartSkuList, Predicate<Sku> predicate)
{
List<Sku> list=new ArrayList<>();
for(Sku sku:cartSkuList)
{
/**
* 根据不同的sku标准判断
*/
if(predicate.test(sku))
{
list.add(sku);
}
}
return list;
}
//Test
public class Version4Test {
public static void main(String[] args) {
CartService cartService = new CartService();
List<Sku> cartSkuList = CartService.getCartSkuList();
cartService.filterSkus(cartSkuList, (Sku sku)->sku.getTotalPrice()>2000).forEach(System.out::println);
}
}
//结果:
Sku{skuId=654032, skuName='无人机', skuPrice=4999.0, totalNum=1, totalPrice=4999.0, skuCategory=ELECTRONICS}
Sku{skuId=642934, skuName='VR-一体机', skuPrice=2299.0, totalNum=1, totalPrice=2299.0, skuCategory=ELECTRONICS}
Sku{skuId=675489, skuName='跑步机', skuPrice=2699.0, totalNum=1, totalPrice=2699.0, skuCategory=SPORTS}
综上所述,当我们所需要的参数类似和返回参数类型与常用的函数式接口有相同时,
我们可以直接调用那些接口,从而节省代码量
2:方法引用
2.1静态方法引用
关于方法引用,我之前一直都是模糊的概念,然后今天突然好像看懂了:
静态方法的调用,直接用类来调用,所以说,Integer.parseInt(number)
这就是一个静态方法,当我们遇到这个时候,我们可以选择使用静态方法的方法引用,也就是目标引用::方法名
2.2指向任意类型实例方法的方法引用
2.3指向现有对象的实例方法的方法引用
3:lambda表达式形式
1: (parameters)->expression
2: (parameters)->{statement;}
4:函数式接口
1:接口中只有一个抽象方法
2:java8的函数式接口注解:@FunctionInterface
3:函数式接口的抽象方法签名:函数描述符
5:原始集合操作与Stream集合操作对比
/**
* 需求如下:
* 1:想看购物车中有什么东西
* 2:图书类的商品都买
* 3:其余商品中,选择最高的两件购买
* 4:只需要两件商品的名称和总价
*/
原始集合操作
public static void oldCartHandle()
{
//CartService cartService = new CartService();
List<Sku> cartSkuList = CartService.getCartSkuList();
//1打印商品
for(Sku sku:cartSkuList)
{
System.out.println(sku);
}
//2 图书类过滤掉
List<Sku> noBook=new ArrayList<>();
for(Sku sku:cartSkuList)
{
if(!sku.getSkuCategory().equals(SkuCategoryEnum.BOOKS))
{
noBook.add(sku);
}
}
//买除了图书类中最高两件
noBook.sort(new Comparator<Sku>() {
//排序,从大到小
@Override
public int compare(Sku sku1, Sku sku2) {
if(sku1.getTotalPrice()>sku2.getTotalPrice()) {
return -1;
}else if(sku1.getTotalPrice()==sku2.getTotalPrice()) {
return 0;
}else {
return 1;
}
}
});
List<Sku> top2SkuList=new ArrayList<>();
//获取价格前二的商品
for(int i=0;i<2;i++)
{
top2SkuList.add(noBook.get(i));
}
//两件商品的总价格
Double money=0.0;
for(Sku sku:top2SkuList)
{
money+=sku.getTotalPrice();
}
//获取两件商品的名称
List<String> resultSkuNameList=new ArrayList<>();
for(Sku sku:top2SkuList)
{
resultSkuNameList.add(sku.getSkuName());
}
System.out.println(resultSkuNameList);
System.out.println(money);
}
Stream集合操作
public static void newCartHandle()
{
//创建原子引用类,在这里防止价格出错
AtomicReference<Double> money=new AtomicReference<>(Double.valueOf(0.0));
List<String> list = CartService.getCartSkuList()
.stream()
//打印商品信息
.peek(sku -> System.out.println(sku))
//过滤掉图书类商品
.filter(sku -> !sku.getSkuCategory().equals(SkuCategoryEnum.BOOKS))
//排序,默认时从小到大,现在对他就行反转,让他从大到小
.sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
//过滤top2价格的商品
.limit(2)
//对金额进行累加
.peek(sku -> money.set(money.get() + sku.getTotalPrice()))
//获取商品名称
.map(sku -> sku.getSkuName())
//对结果进行收集
.collect(Collectors.toList());
System.out.println(list);
System.out.println(money);
}
6:流的组成
流操作分类
流的使用
流使用实例
public class StreamOperator {
/**
* filter在流式编程中起到过滤的作用,
* 只有符合条件才不会被过滤掉
* 结果:
* Sku{skuId=654032, skuName='无人机', skuPrice=4999.0, totalNum=1, totalPrice=4999.0, skuCategory=ELECTRONICS}
* Sku{skuId=642934, skuName='VR-一体机', skuPrice=2299.0, totalNum=1, totalPrice=2299.0, skuCategory=ELECTRONICS}
* Sku{skuId=645321, skuName='纯色衬衫', skuPrice=409.0, totalNum=3, totalPrice=1227.0, skuCategory=CLOTHING}
* Sku{skuId=654327, skuName='牛仔裤', skuPrice=528.0, totalNum=1, totalPrice=528.0, skuCategory=CLOTHING}
* Sku{skuId=675489, skuName='跑步机', skuPrice=2699.0, totalNum=1, totalPrice=2699.0, skuCategory=SPORTS}
*/
public static void filterTest()
{
List<Sku> cartSkuList = CartService.getCartSkuList();
cartSkuList.stream()
.filter(sku -> !SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory()))
.forEach(System.out::println);
}
/**
* map的使用中,观看他的底层,是function,
* 在这里,他主要实现的就是映射的作用,也就是传入一个类型,然后映射为其他类型,
* 在本例子中,他就是把sku类,映射为sku.getSkuName()字段
* 结果:
* 无人机
* VR-一体机
* 纯色衬衫
* 牛仔裤
* 跑步机
* JAVA核心技术
* 算法
* TensorFlow进阶指南
*/
public static void mapTest()
{
List<Sku> cartSkuList = CartService.getCartSkuList();
cartSkuList.stream()
.map(sku -> sku.getSkuName())
.forEach(System.out::println);
}
/**
* 将一个对象转换为一个流的操作
*/
public static void flatMapTest()
{
List<Sku> cartSkuList = CartService.getCartSkuList();
cartSkuList.stream()
.flatMap(sku -> Arrays.stream(sku.getSkuName().split("")))
.forEach(System.out::println);
}
/**
* peek 的作用是遍历的作用,他和foreach本质上的区别是,
* peek处理过后,流还可以继续操作,而foreach不行
* 结果:
* 无人机
* Sku{skuId=654032, skuName='无人机', skuPrice=4999.0, totalNum=1, totalPrice=4999.0, skuCategory=ELECTRONICS}
* VR-一体机
* Sku{skuId=642934, skuName='VR-一体机', skuPrice=2299.0, totalNum=1, totalPrice=2299.0, skuCategory=ELECTRONICS}
* 纯色衬衫
* Sku{skuId=645321, skuName='纯色衬衫', skuPrice=409.0, totalNum=3, totalPrice=1227.0, skuCategory=CLOTHING}
* 牛仔裤
* Sku{skuId=654327, skuName='牛仔裤', skuPrice=528.0, totalNum=1, totalPrice=528.0, skuCategory=CLOTHING}
* 跑步机
* Sku{skuId=675489, skuName='跑步机', skuPrice=2699.0, totalNum=1, totalPrice=2699.0, skuCategory=SPORTS}
* JAVA核心技术
* Sku{skuId=678678, skuName='JAVA核心技术', skuPrice=149.0, totalNum=1, totalPrice=149.0, skuCategory=BOOKS}
* 算法
* Sku{skuId=697894, skuName='算法', skuPrice=78.2, totalNum=1, totalPrice=78.2, skuCategory=BOOKS}
* TensorFlow进阶指南
* Sku{skuId=696968, skuName='TensorFlow进阶指南', skuPrice=85.1, totalNum=1, totalPrice=85.1, skuCategory=BOOKS}
*
* **从结果可以看出,并不是peek全部执行完之后,foreach才执行完,交替执行
*/
public static void peek()
{
List<Sku> cartSkuList = CartService.getCartSkuList();
cartSkuList.stream()
//peek一次遍历
.peek(sku -> System.out.println(sku.getSkuName()))
//forEach一次遍历
.forEach(System.out::println);
}
/**
* sorted的作用就是排序的作用
* 没有加peek方法之前的结果:
* Sku{skuId=697894, skuName='算法', skuPrice=78.2, totalNum=1, totalPrice=78.2, skuCategory=BOOKS}
* Sku{skuId=696968, skuName='TensorFlow进阶指南', skuPrice=85.1, totalNum=1, totalPrice=85.1, skuCategory=BOOKS}
* Sku{skuId=678678, skuName='JAVA核心技术', skuPrice=149.0, totalNum=1, totalPrice=149.0, skuCategory=BOOKS}
* Sku{skuId=654327, skuName='牛仔裤', skuPrice=528.0, totalNum=1, totalPrice=528.0, skuCategory=CLOTHING}
* Sku{skuId=645321, skuName='纯色衬衫', skuPrice=409.0, totalNum=3, totalPrice=1227.0, skuCategory=CLOTHING}
* Sku{skuId=642934, skuName='VR-一体机', skuPrice=2299.0, totalNum=1, totalPrice=2299.0, skuCategory=ELECTRONICS}
* Sku{skuId=675489, skuName='跑步机', skuPrice=2699.0, totalNum=1, totalPrice=2699.0, skuCategory=SPORTS}
* Sku{skuId=654032, skuName='无人机', skuPrice=4999.0, totalNum=1, totalPrice=4999.0, skuCategory=ELECTRONICS}
*
* 加了peek方法之后
* 无人机
* VR-一体机
* 纯色衬衫
* 牛仔裤
* 跑步机
* JAVA核心技术
* 算法
* TensorFlow进阶指南
* Sku{skuId=697894, skuName='算法', skuPrice=78.2, totalNum=1, totalPrice=78.2, skuCategory=BOOKS}
* Sku{skuId=696968, skuName='TensorFlow进阶指南', skuPrice=85.1, totalNum=1, totalPrice=85.1, skuCategory=BOOKS}
* Sku{skuId=678678, skuName='JAVA核心技术', skuPrice=149.0, totalNum=1, totalPrice=149.0, skuCategory=BOOKS}
* Sku{skuId=654327, skuName='牛仔裤', skuPrice=528.0, totalNum=1, totalPrice=528.0, skuCategory=CLOTHING}
* Sku{skuId=645321, skuName='纯色衬衫', skuPrice=409.0, totalNum=3, totalPrice=1227.0, skuCategory=CLOTHING}
* Sku{skuId=642934, skuName='VR-一体机', skuPrice=2299.0, totalNum=1, totalPrice=2299.0, skuCategory=ELECTRONICS}
* Sku{skuId=675489, skuName='跑步机', skuPrice=2699.0, totalNum=1, totalPrice=2699.0, skuCategory=SPORTS}
* Sku{skuId=654032, skuName='无人机', skuPrice=4999.0, totalNum=1, totalPrice=4999.0, skuCategory=ELECTRONICS}
*/
public static void sortTest()
{
List<Sku> cartSkuList = CartService.getCartSkuList();
cartSkuList.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.sorted(Comparator.comparing(Sku::getTotalPrice))
.forEach(System.out::println);
}
public static void main(String[] args) {
sortTest();
}
}
7:springcloud alibab学习中使用的lamdba
实体类EcommerceAddress (po)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "t_ecommerce_address")
public class EcommerceAddress {
/** 自增主键 */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
/** 用户 id */
@Column(name = "user_id", nullable = false)
private Long userId;
/** 用户名 */
@Column(name = "username", nullable = false)
private String username;
/** 电话 */
@Column(name = "phone", nullable = false)
private String phone;
/** 省 */
@Column(name = "province", nullable = false)
private String province;
/** 市 */
@Column(name = "city", nullable = false)
private String city;
/** 详细地址 */
@Column(name = "address_detail", nullable = false)
private String addressDetail;
/** 创建时间 */
@CreatedDate
@Column(name = "create_time", nullable = false)
private Date createTime;
/** 更新时间 */
@LastModifiedDate
@Column(name = "update_time", nullable = false)
private Date updateTime;
/**
* 根据userId+AddressItem 得到EcommerceAddress
* 也就是将dto 转换为实体类
* @param userId
* @param addressItem
* @return
*/
public static EcommerceAddress to(Long userId,AddressInfo.AddressItem addressItem)
{
/**
* 方法一
* EcommerceAddress ecommerceAddress = new EcommerceAddress();
* BeanUtils.copyProperties(addressItem,ecommerceAddress);
* ecommerceAddress.setUserId(userId);
* return ecommerceAddress;
*/
EcommerceAddress ecommerceAddress = new EcommerceAddress();
ecommerceAddress.setUserId(userId);
ecommerceAddress.setUsername(addressItem.getUsername());
ecommerceAddress.setProvince(addressItem.getProvince());
ecommerceAddress.setAddressDetail(addressItem.getAddressDetail());
ecommerceAddress.setCity(addressItem.getCity());
ecommerceAddress.setPhone(addressItem.getPhone());
return ecommerceAddress;
}
/**
* 将EcommerceAddress 转换为AddressItem
* 也就是将实体类转换为dto对象
* @return
*/
public AddressInfo.AddressItem toAddressItem()
{
AddressInfo.AddressItem addressItem = new AddressInfo.AddressItem();
addressItem.setId(this.id);
addressItem.setAddressDetail(this.addressDetail);
addressItem.setCity(this.city);
addressItem.setPhone(this.phone);
addressItem.setUsername(this.username);
addressItem.setProvince(this.province);
addressItem.setCreateTime(this.createTime);
addressItem.setUpdateTime(this.updateTime);
return addressItem;
}
}
实体类AddressInfo (dto)
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "用户地址信息")
public class AddressInfo {
@ApiModelProperty(value = "地址所属用户 id")
private Long userId;
@ApiModelProperty(value = "地址详细信息")
private List<AddressItem> addressItems;
@ApiModel(description = "用户的单个地址信息")
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class AddressItem{
@ApiModelProperty(value = "地址表主键 id")
private Long id;
@ApiModelProperty(value = "用户姓名")
private String username;
@ApiModelProperty(value = "电话")
private String phone;
@ApiModelProperty(value = "省")
private String province;
@ApiModelProperty(value = "市")
private String city;
@ApiModelProperty(value = "详细的地址")
private String addressDetail;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
public AddressItem(Long id) {
this.id = id;
}
/**
* 将AddressItem 转换为UserAddress
* @return
*/
public UserAddress toUserAddress()
{
UserAddress userAddress = new UserAddress();
userAddress.setAddressDetail(this.addressDetail);
userAddress.setCity(this.city);
userAddress.setPhone(this.phone);
userAddress.setProvince(this.province);
userAddress.setUsername(this.username);
return userAddress;
}
}
}
实体类UserAddress (vo)
@ApiModel(description = "用户地址信息")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserAddress {
@ApiModelProperty(value = "用户姓名")
private String username;
@ApiModelProperty(value = "电话")
private String phone;
@ApiModelProperty(value = "省")
private String province;
@ApiModelProperty(value = "市")
private String city;
@ApiModelProperty(value = "详细的地址")
private String addressDetail;
}
通用id对象
@Data
@ApiModel(description = "通用id对象")
@NoArgsConstructor
@AllArgsConstructor
public class TableId {
@ApiModelProperty(value = "数据表记录主键")
private List<Id> ids;
@Data
@ApiModel(description = "数据表记录主键对象")
@NoArgsConstructor
@AllArgsConstructor
public static class Id{
@ApiModelProperty(value = "数据表记录主键")
private Long id;
}
}
lamdba使用
//1:将dto中的数据转为vo列表
List<EcommerceAddress> ecommerceAddressList=addressInfo
.getAddressItems()
.stream()
//map的使用就是转换
.map(a-> EcommerceAddress.to(loginUserInfo.getId(),a))
.collect(Collectors.toList());
//2:获取列表中的id,并且集成为一个列表
List<EcommerceAddress> saveRecords=ecommerceAddressDao.saveAll(ecommerceAddressList);
//使用map获取一个变量
List<Long> ids=saveRecords.stream().map(EcommerceAddress::getId).collect(Collectors.toList());
//3:构造一个对象
return new TableId(
//这个可以构造一个list
ids.stream().map(TableId.Id::new).collect(Collectors.toList())
);
//4:指向实例中的方法
List<EcommerceAddress> ecommerceAddressList = ecommerceAddressDao.findAllByUserId(loginUserInfo.getId());
List<AddressInfo.AddressItem> addressItems = ecommerceAddressList
.stream()
//指向实例中的方法
.map(EcommerceAddress::toAddressItem)
.collect(Collectors.toList());
//将list转换为map对象
List<SimpleGoodsInfo> goodsInfos=notSecuredGoodsClient.getSimpleGoodsInfoByTableId(tableId).getData();
Map<Long,SimpleGoodsInfo> goodsId2GoodsInfo=goodsInfos.stream()
.collect(Collectors.toMap(SimpleGoodsInfo::getId, Function.identity()));