You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写支持多参数函数的泛型toSlice流转换方法?

问题

我现有一个用于将Page对象转换为Slice的泛型方法:

public static <T,R> Slice<R> toSlice(final Page<T> source, Function<T,R> transform) {
  return Slice.<R>builder()
      .totalPages(BigInteger.valueOf(source.getTotalPages()))
      .pageData(source.stream()
          .map(transform)
          .collect(Collectors.toList()))
      .build();
}

平时我是这样使用该方法的:

return SliceFactory.toSlice(
            someDao.findAll(
                    predicate,
                    PageRequest.of(page, PAGE_SIZE,
                        Sort.by(Sort.Direction.DESC, DEFAULT_SORTING_PROPERTY))),
            dtoFactory::toSomeDto);

现在需要给dtoFactory.toSomeDto()传入额外参数,请问如何改造现有toSlice方法为支持该需求的泛型方法?

解决方案

1. 支持单个额外参数的改造

如果仅需传入一个额外参数,可以将原方法的Function<T,R>替换为BiFunction<T, U, R>,新增泛型参数U来定义额外参数的类型:

public static <T, U, R> Slice<R> toSlice(final Page<T> source, 
                                         final U extraParam,
                                         final BiFunction<T, U, R> transform) {
    return Slice.<R>builder()
        .totalPages(BigInteger.valueOf(source.getTotalPages()))
        .pageData(source.stream()
            .map(item -> transform.apply(item, extraParam))
            .collect(Collectors.toList()))
        .build();
}

使用示例:
假设toSomeDto需要接收一个UserContext类型的额外参数,调用方式如下:

UserContext userContext = new UserContext();
return SliceFactory.toSlice(
            someDao.findAll(
                    predicate,
                    PageRequest.of(page, PAGE_SIZE,
                        Sort.by(Sort.Direction.DESC, DEFAULT_SORTING_PROPERTY))),
            userContext,
            dtoFactory::toSomeDto);

2. 支持多个额外参数的改造

若需传入多个参数,推荐采用参数封装的方式,也可使用可变参数(不推荐):

方式一:自定义参数类封装

将所有额外参数封装到一个专用类中,比如ConvertParams,再通过BiFunction传递:

// 自定义参数封装类
public class ConvertParams {
    private UserContext userContext;
    private Locale locale;
    // 构造器、Getter、Setter
}

// 改造后的toSlice方法
public static <T, P, R> Slice<R> toSlice(final Page<T> source, 
                                         final P params,
                                         final BiFunction<T, P, R> transform) {
    return Slice.<R>builder()
        .totalPages(BigInteger.valueOf(source.getTotalPages()))
        .pageData(source.stream()
            .map(item -> transform.apply(item, params))
            .collect(Collectors.toList()))
        .build();
}

使用示例:

ConvertParams params = new ConvertParams(userContext, Locale.CHINA);
return SliceFactory.toSlice(
            someDao.findAll(predicate, PageRequest.of(page, PAGE_SIZE, Sort.by(Sort.Direction.DESC, DEFAULT_SORTING_PROPERTY))),
            params,
            dtoFactory::toSomeDto);

方式二:可变参数结合Function(不推荐)

这种方式无需封装类,但需要手动强转参数,可读性与安全性较差:

@SuppressWarnings("unchecked")
public static <T, R> Slice<R> toSlice(final Page<T> source, 
                                      final Function<T, Object[], R> transform,
                                      final Object... extraParams) {
    return Slice.<R>builder()
        .totalPages(BigInteger.valueOf(source.getTotalPages()))
        .pageData(source.stream()
            .map(item -> transform.apply(item, extraParams))
            .collect(Collectors.toList()))
        .build();
}

使用示例:

return SliceFactory.toSlice(
            someDao.findAll(predicate, PageRequest.of(page, PAGE_SIZE, Sort.by(Sort.Direction.DESC, DEFAULT_SORTING_PROPERTY))),
            (item, params) -> dtoFactory.toSomeDto(item, (UserContext) params[0], (Locale) params[1]),
            userContext, Locale.CHINA);

3. 保留原有方法兼容性

如果不想破坏现有代码的调用逻辑,可以通过方法重载同时保留原有的无额外参数版本:

// 原有方法保持不变
public static <T,R> Slice<R> toSlice(final Page<T> source, Function<T,R> transform) {
    return Slice.<R>builder()
        .totalPages(BigInteger.valueOf(source.getTotalPages()))
        .pageData(source.stream()
            .map(transform)
            .collect(Collectors.toList()))
        .build();
}

// 新增支持单个额外参数的重载方法
public static <T, U, R> Slice<R> toSlice(final Page<T> source, 
                                         final U extraParam,
                                         final BiFunction<T, U, R> transform) {
    return Slice.<R>builder()
        .totalPages(BigInteger.valueOf(source.getTotalPages()))
        .pageData(source.stream()
            .map(item -> transform.apply(item, extraParam))
            .collect(Collectors.toList()))
        .build();
}

这样原有代码无需修改,新需求场景直接使用重载后的方法即可。


内容的提问来源于stack exchange,提问作者benjaminv2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:05:26