闽公网安备 35020302035485号
1.用Function封装类型转换逻辑 在数据处理中,类型转换是高频操作。
重复编写转换代码不仅冗余,还会增加维护成本。借助Function,我们可将转换逻辑封装为独立组件,实现一次定义、多处复用。
import java.util.function.Function;
public class TypeConversion {
// 定义String转Integer的Function,处理可能的转换异常
public static final Function<String, Integer> STRING_TO_INTEGER = str -> {
if (str == null || str.isEmpty()) { // 检查输入是否为空
return 0; // 空值时返回默认值
}
try {
return Integer.parseInt(str); // 执行转换
} catch (NumberFormatException e) {
return 0; // 转换失败时返回默认值
}
};
public static void main(String[] args) {
String numStr = "123";
Integer num = STRING_TO_INTEGER.apply(numStr); // 应用转换逻辑
System.out.println(num); // 输出:123
}
}
代码解析:通过定义静态Function常量STRING_TO_INTEGER,我们将String到Integer的转换逻辑(包括空值处理和异常捕获)封装其中。在main方法中,只需调用apply方法即可完成转换,无需重复编写校验与转换代码。import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class StreamWithFunction {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("1", "2", "3", "4");
// 定义String转Integer的Function
Function<String, Integer> toInt = Integer::parseInt;
// 堆代码 duidaima.com
// 结合Stream使用Function:转换后过滤出偶数,再转为String
List<String> result = stringList.stream()
.map(toInt) // 应用转换
.filter(num -> num % 2 == 0) // 过滤偶数
.map(String::valueOf) // 转回String
.collect(Collectors.toList());
System.out.println(result); // 输出:[2, 4]
}
}
代码解析:首先定义String转Integer的Function,在Stream流中通过map方法应用该Function完成类型转换,后续链式调用filter和map完成过滤与二次转换。整个过程无需中间变量,逻辑清晰可见。import java.util.function.Function;
public class FunctionChaining {
public static void main(String[] args) {
// 第一步:String转Integer
Function<String, Integer> strToInt = Integer::parseInt;
// 第二步:Integer加10
Function<Integer, Integer> addTen = num -> num + 10;
// 第三步:Integer转String
Function<Integer, String> intToStr = String::valueOf;
// 组合函数链:str -> int -> int+10 -> str
Function<String, String> chain = strToInt.andThen(addTen).andThen(intToStr);
String result = chain.apply("5"); // 应用函数链
System.out.println(result); // 输出:15
}
}
代码解析:通过andThen方法,我们将strToInt、addTen、intToStr三个Function按顺序组合为chain。调用apply时,输入的"5"会依次经过三步处理,最终得到"15"。andThen按"先当前后参数"的顺序执行,compose则相反(先参数后当前)。import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class DynamicFunctionSelection {
// 定义操作类型
enum Operation { ADD, SUBTRACT, MULTIPLY }
public static void main(String[] args) {
// 用Map存储操作类型与对应Function的映射
Map<Operation, Function<Integer[], Integer>> operationMap = new HashMap<>();
operationMap.put(Operation.ADD, nums -> nums[0] + nums[1]); // 加法逻辑
operationMap.put(Operation.SUBTRACT, nums -> nums[0] - nums[1]); // 减法逻辑
operationMap.put(Operation.MULTIPLY, nums -> nums[0] * nums[1]); // 乘法逻辑
// 动态选择操作:根据Operation获取对应的Function并执行
Integer result = operationMap.get(Operation.ADD).apply(new Integer[]{3, 5});
System.out.println(result); // 输出:8
}
}
代码解析:通过Map建立Operation与Function的映射,每种操作对应一个计算逻辑。当需要执行运算时,只需根据Operation从Map中获取对应的Function并调用apply,无需if-else判断。import java.util.function.Function;
// 定义带异常处理的Function包装类
@FunctionalInterface
interface ThrowingFunction<T, R, E extends Exception> {
R apply(T t) throws E;
}
public class FunctionWithException {
// 包装方法:处理异常并转换为普通Function
public static <T, R, E extends Exception> Function<T, R> wrap(ThrowingFunction<T, R, E> throwingFunc) {
return t -> {
try {
return throwingFunc.apply(t); // 执行带异常的逻辑
} catch (Exception e) {
throw new RuntimeException(e); // 包装为运行时异常抛出
}
};
}
public static void main(String[] args) {
// 使用包装类处理可能抛异常的转换(如Integer.parseInt可能抛NumberFormatException)
Function<String, Integer> safeParser = wrap(Integer::parseInt);
Integer result = safeParser.apply("123"); // 正常转换
System.out.println(result); // 输出:123
}
}
代码解析:定义ThrowingFunction接口允许抛出异常,通过wrap方法将其转换为普通Function,并在内部捕获异常并包装为RuntimeException。这样既保留了异常处理能力,又符合Function的接口规范。import java.util.Optional;
import java.util.function.Function;
class User {
private String name;
private Address address;
// 构造器、getter省略
public User(String name, Address address) {
this.name = name;
this.address = address;
}
public String getName() { return name; }
public Address getAddress() { return address; }
}
class Address {
private String city;
// 构造器、getter省略
public Address(String city) { this.city = city; }
public String getCity() { return city; }
}
public class OptionalWithFunction {
public static void main(String[] args) {
User user = new User("Alice", new Address("Beijing"));
// 定义从User获取城市的Function链
Function<User, Address> getUserAddress = User::getAddress;
Function<Address, String> getCity = Address::getCity;
// 结合Optional:安全获取城市,避免空指针
String city = Optional.ofNullable(user)
.map(getUserAddress) // 提取Address,若为null则终止
.map(getCity) // 提取city,若为null则终止
.orElse("Unknown"); // 最终为null时返回默认值
System.out.println(city); // 输出:Beijing
}
}
代码解析:通过Optional的map方法,依次应用getUserAddress和getCity两个Function。若链中任何一步返回null,后续操作会终止,最终通过orElse返回默认值,全程无需显式null判断。import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
class User {
private Long id;
public User(Long id) { this.id = id; }
public Long getId() { return id; }
}
class Order {
private Long orderId;
public Order(Long orderId) { this.orderId = orderId; }
public Long getOrderId() { return orderId; }
}
public class GenericDataExtractor {
// 通用提取方法:从列表中提取指定字段
public static <T, R> List<R> extract(List<T> list, Function<T, R> extractor) {
List<R> result = new ArrayList<>();
for (T item : list) {
result.add(extractor.apply(item)); // 应用提取规则
}
return result;
}
public static void main(String[] args) {
List<User> users = List.of(new User(1L), new User(2L));
List<Order> orders = List.of(new Order(100L), new Order(101L));
// 提取用户ID
List<Long> userIds = extract(users, User::getId);
// 提取订单ID
List<Long> orderIds = extract(orders, Order::getOrderId);
System.out.println(userIds); // 输出:[1, 2]
System.out.println(orderIds); // 输出:[100, 101]
}
}
代码解析:extract方法通过接收Function参数extractor,将数据提取逻辑与遍历逻辑分离。对于User和Order两种不同对象,只需传入对应的提取函数(User::getId和Order::getOrderId),即可复用同一提取方法。import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class CachedFunction {
private final Map<Object, Object> cache = new HashMap<>(); // 缓存容器
// 缓存包装方法:先查缓存,无则计算并缓存结果
public <T, R> R computeIfAbsent(T key, Function<T, R> computeFunc) {
if (cache.containsKey(key)) { // 检查缓存
return (R) cache.get(key); // 返回缓存值
}
R result = computeFunc.apply(key); // 执行计算
cache.put(key, result); // 存入缓存
return result;
}
public static void main(String[] args) {
CachedFunction cached = new CachedFunction();
// 定义耗时计算:模拟数据库查询
Function<Long, String> dbQuery = id -> {
System.out.println("Executing query for id: " + id);
return "User_" + id;
};
// 第一次查询:计算并缓存
String user1 = cached.computeIfAbsent(1L, dbQuery);
// 第二次查询:直接返回缓存
String user2 = cached.computeIfAbsent(1L, dbQuery);
System.out.println(user1); // 输出:User_1
System.out.println(user2); // 输出:User_1
}
}
代码解析:computeIfAbsent方法接收缓存键key和计算函数computeFunc,先检查缓存中是否存在key,存在则返回缓存值,否则执行computeFunc计算并缓存结果。核心计算逻辑由Function封装,与缓存控制分离。import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
// 订单类
class Order {
private double amount;
private String userType;
public Order(double amount, String userType) {
this.amount = amount;
this.userType = userType;
}
public double getAmount() { return amount; }
public String getUserType() { return userType; }
}
public class StrategyWithFunction {
public static void main(String[] args) {
// 定义不同用户类型的折扣策略(Function<订单, 折后金额>)
Map<String, Function<Order, Double>> discountStrategies = new HashMap<>();
discountStrategies.put("NEW", order -> order.getAmount() * 0.8); // 新用户8折
discountStrategies.put("MEMBER", order -> order.getAmount() * 0.9); // 会员9折
discountStrategies.put("DEFAULT", order -> order.getAmount()); // 默认无折扣
// 计算订单金额
Order order = new Order(100.0, "NEW");
double finalAmount = discountStrategies.getOrDefault(
order.getUserType(),
discountStrategies.get("DEFAULT")
).apply(order);
System.out.println(finalAmount); // 输出:80.0
}
}
代码解析:用Map存储用户类型与折扣策略(Function)的映射,每个策略直接通过Lambda表达式定义,无需单独创建策略类。计算订单金额时,根据用户类型获取对应的Function并执行,完成折扣计算。import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
// 订单DTO
class OrderDTO {
private String orderNo;
private String userId;
private double amount;
// 构造器、getter省略
public OrderDTO(String orderNo, String userId, double amount) {
this.orderNo = orderNo;
this.userId = userId;
this.amount = amount;
}
public String getOrderNo() { return orderNo; }
public String getUserId() { return userId; }
public double getAmount() { return amount; }
}
// 订单实体
class OrderEntity {
private Long id;
private String orderNo;
private Long userId;
private double finalAmount;
// 构造器、getter、setter省略
public OrderEntity(Long id, String orderNo, Long userId, double finalAmount) {
this.id = id;
this.orderNo = orderNo;
this.userId = userId;
this.finalAmount = finalAmount;
}
@Override
public String toString() {
return "OrderEntity{id=" + id + ", orderNo='" + orderNo + "'}";
}
}
public class ProjectApplication {
public static void main(String[] args) {
// 1. DTO转实体的基础转换
Function<OrderDTO, OrderEntity> baseConverter = dto ->
new OrderEntity(null, dto.getOrderNo(), null, dto.getAmount());
// 2. 补充用户ID(String转Long)
Function<OrderEntity, OrderEntity> addUserId = entity -> {
String userIdStr = "123"; // 实际从上下文获取
entity = new OrderEntity(entity.getId(), entity.getOrderNo(),
Long.parseLong(userIdStr), entity.getFinalAmount());
return entity;
};
// 3. 应用折扣策略
Function<OrderEntity, OrderEntity> applyDiscount = entity -> {
double discounted = entity.getFinalAmount() * 0.9; // 会员折扣
return new OrderEntity(entity.getId(), entity.getOrderNo(),
entity.getUserId(), discounted);
};
// 4. 组合转换链:DTO→基础实体→补充用户ID→应用折扣
Function<OrderDTO, OrderEntity> fullConverter = baseConverter
.andThen(addUserId)
.andThen(applyDiscount);
// 5. 批量处理订单
List<OrderDTO> dtos = List.of(
new OrderDTO("ORD001", "123", 100.0),
new OrderDTO("ORD002", "123", 200.0)
);
// 堆代码 duidaima.com
List<OrderEntity> entities = dtos.stream()
.map(fullConverter)
.collect(Collectors.toList());
System.out.println(entities);
// 输出:[OrderEntity{id=null, orderNo='ORD001'}, OrderEntity{id=null, orderNo='ORD002'}]
}
}
代码解析:在订单处理流程中,首先定义DTO到实体的基础转换Function,再通过andThen组合补充用户ID和应用折扣的Function,形成完整转换链。结合Stream的map方法,实现批量DTO到实体的转换,逻辑清晰且易于扩展。