去除Java中的重载方法

sdnqo3pr  于 2023-01-11  发布在  Java
关注(0)|答案(5)|浏览(158)

有2个重载方法。
这些方法中的每一个都将一种类型的列表转换为另一种类型的列表。但是第一个方法使用了比较器。

class SomeClass {
    public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                                 Function<T, G> mapperFunction, 
                                                 Comparator<? super G> comparator) {
           return Stream.ofNullable(inputList)
                        .flatMap(List::stream)
                        .map(mapperFunction)
                        .sorted(comparator)
                        .collect(Collectors.toList());
    }
    public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                                 Function<T, G> mapperFunction) {
           return Stream.ofNullable(inputList)
                        .flatMap(List::stream)
                        .map(mapperFunction)
                        .collect(Collectors.toList());
    }
}

正如你所看到的,大部分代码行都是重复的,我怎样才能去掉第二个方法,这样传递null给第一个比较器就不会破坏它呢?
换句话说,如何在没有比较器的情况下使第一个工作?

rt4zxlrg

rt4zxlrg1#

使用if语句检查null

public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                             Function<T, G> mapperFunction,
                                             Comparator<? super G> comparator) {
    Stream<G> stream = Stream.ofNullable(inputList)
            .flatMap(List::stream)
            .map(mapperFunction);
    if (comparator != null)
        stream = stream.sorted(comparator);
    return stream.collect(Collectors.toList());
}

public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                             Function<T, G> mapperFunction) {
    return toListOfNewType(inputList, mapperFunction, null);
}
yshpjwxd

yshpjwxd2#

虽然我支持在实现方面消除代码重复的目标,但我考虑为null赋予一个特殊的含义,而不是明确重载方法是朝着错误方向迈出的一步。
为了方便调用者,您仍然可以有两个方法,在实现中没有代码重复,例如:

public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                             Function<T, G> mapperFunction,
                                             Comparator<? super G> comparator) {
  List<G> resultList = toListOfNewType(inputList, mapperFunction);
  if(!resultList.isEmpty()) resultList.sort(comparator);
  return resultList;
}
public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                             Function<T, G> mapperFunction) {
  return inputList==null? Collections.emptyList():
    inputList.stream().map(mapperFunction).collect(Collectors.toCollection(ArrayList::new));
}

我甚至会考虑放弃对null输入列表的支持,因为这只会导致隐藏问题而不是解决问题。
另一种办法是:

public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                             Function<T, G> mapperFunction,
                                             Comparator<? super G> comparator) {
  return toListOfNewTypeImpl(inputList, mapperFunction, s -> s.sorted(comparator));
}
public static <T, G> List<G> toListOfNewType(List<T> inputList,
                                             Function<T, G> mapperFunction) {
  return toListOfNewTypeImpl(inputList, mapperFunction, UnaryOperator.identity());
}
private static <T, G> List<G> toListOfNewTypeImpl(List<T> inputList,
                                                  Function<T, G> mapperFunction,
                                                  UnaryOperator<Stream<G>> lastOp) {
  return lastOp.apply(inputList.stream().map(mapperFunction)).collect(Collectors.toList());
}
cl25kdpy

cl25kdpy3#

我可能只是用一个非常小的输入进行了测试(当然,即使在不需要的时候,执行元素比较的效率也会降低),但可能这样做就可以了:

public static <T, G> List<G> toListOfNewType(List<T> inputList, Function<T, G> mapperFunction) {
    return toListOfNewType(inputList, mapperFunction, (a, b) -> 0);
}
4nkexdtk

4nkexdtk4#

在我的团队中,在一些代码评审中,这也是一个有趣的问题...这里的问题是,如果你允许nullableComparator,你就有点违背了这个目的。argumentComparatornull是 * 自然顺序 * 排序的完全有效的含义,这意味着这是完全有效的:

List<Integer> list = new ArrayList<>();
list.add(2);
list.add(1);

Collections.sort(list, null);

即使您的 * 内部 * 实现不允许这样做,也就是说:

List.of(4, 3, 2)
     .stream()
     .sorted(null)
     .forEachOrdered(System.out::println);

会抛出NullPointerException
因此,* 除非 * 您清楚地记录了您对该方法的意图,否则用户可能会感到困惑(我会)。
恕我直言,要“复制”的代码并不多,您可以强制用户传递一个Function,该Function返回Comparable的“某个东西”,方法是:

public static <T, G extends Comparable<? extends G>> List<G> sortedToListOfNewType(
    List<T> inputList,
    Function<T, G> mapperFunction) {

    return Stream.ofNullable(inputList)
                 .flatMap(List::stream)
                 .map(mapperFunction)
                 .sorted()
                 .collect(Collectors.toList());
}

public static <T, G> List<G> toListOfNewType(
    List<T> inputList,
    Function<T, G> mapperFunction) {

    return Stream.ofNullable(inputList)
                 .flatMap(List::stream)
                 .map(mapperFunction)
                 .collect(Collectors.toList());
}

缺点是:1)重复代码--你试图避免的一切意味着它似乎2)这些不能被重载的方法--因为擦除是相同的,编译器不允许这样做。
但是,正如所说,这种方法是非常主观的。

q5lcpyga

q5lcpyga5#

我不认为有一个简单的方法来做到这一点,或者我不知道。但如果你想试试我的图书馆:abacus-common,您可以执行以下操作:

StreamEx.of(inputList)
    .map(mapperFunction)
    .__(s -> comparator == null ? s : s.sort(comparator))
    .toList()

相关问题