小编典典

转换清单 到清单 (或任何扩展Number的类)

java

我想创建一个非常通用的实用程序方法,以获取任何Collection并将其转换为用户可选类的Collection,该类从Number扩展(Long,Double,Float,Integer等)

我想到了使用Google集合来转换集合并返回不可变列表的代码。

import java.util.List;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
     * Takes a {@code List<String>} and transforms it into a list of the
     * specified {@code clazz}.
     * 
     * @param <T>
     * @param stringValues
     *            the list of Strings to be used to create the list of the
     *            specified type
     * @param clazz
     *            must be a subclass of Number. Defines the type of the new List
     * @return
     */
    public static <T extends Number> List<T> toNumberList(List<String> stringValues, final Class<T> clazz) {
        List<T> ids = Lists.transform(stringValues, new Function<String, T>() {
            @SuppressWarnings("unchecked")
            @Override
            public T apply(String from) {
                T retVal = null;
                if (clazz.equals(Integer.class)) {
                    retVal = (T) Integer.valueOf(from);
                } else if (clazz.equals(Long.class)) {
                    retVal = (T) Long.valueOf(from);
                } else if (clazz.equals(Float.class)) {
                    retVal = (T) Float.valueOf(from);
                } else if (clazz.equals(Double.class)) {
                    retVal = (T) Double.valueOf(from);
                } else {
                    throw new RuntimeException(String.format("Type %s is not supported (yet)", clazz.getName()));
                }
                return retVal;
            }
        });
        return ImmutableList.copyOf(ids);
    }

可以这样使用:

// Convert List<String> to List<Long>
List<Long> ids = MiscUtils.toNumberList(productIds, Long.class);

是我的代码过度杀伤力,还是您将如何简化它,同时又使其足够通用?


阅读 167

收藏
2020-11-16

共1个答案

小编典典

我认为这段代码最重要的方面是Function方法本身。我也认为切换Function主体中允许的子类没有任何意义,因为您已经知道Number要在Function创建子类时返回哪种类型的子类。如果给出的话,您的方法也会失败,这也是一个小问题BigInteger.class

鉴于此,我要做的是创建一个实用工具类(我们称之为它Numbers),并在其上提供方法,使每个方法返回一个Function(可以是enum单例)将a解析String为特定类型的方法Number。那是:

public class Numbers {
  public static Function<String, Integer> parseIntegerFunction() { ... }
  public static Function<String, Long> parseLongFunction() { ... }
  ...
}

它们每个都可以这样实现:

public static Function<String, Integer> parseIntegerFunction() {
  return ParseIntegerFunction.INSTANCE;
}

private enum ParseIntegerFunction implements Function<String, Integer> {
  INSTANCE;

  public Integer apply(String input) {
    return Integer.valueOf(input);
  }

  @Override public String toString() {
    return "ParseIntegerFunction";
  }
}

然后可以使用此功能,但用户需要:

List<String> strings = ...
List<Integer> integers = Lists.transform(strings, Numbers.parseIntegerFunction());

与您的方法相比,此方法有很多优点:

  • 不需要任何切换Function。。。我们知道我们要创建哪种类型的号码,只需执行此操作即可。快点。
  • 更加灵活,因为每个都Function可以在任何地方使用…用户不必像您的方法那样使用它(将转换后的值复制到中ImmutableList
  • 您仅创建Function您实际要允许的。如果没有BigInteger解析功能,则用户只能调用它,而不是像在您的示例中那样在编译时完全合法然后在运行时失败是完全合法的。

附带说明一下,我建议将返回ImmutableListbe ImmutableList而不是List
的任何方法的返回类型设为…,它提供对该方法的客户有用的信息。

编辑:

如果您 确实需要 更多动态的东西(即,您希望具有某些实例的类Class<T extends Number>能够将Strings转换为该Number类型),则还可以添加如下查找方法:

public static <T extends Number> Function<String, T> parseFunctionFor(Class<T> type) {
  // lookup the function for the type in an ImmutableMap and return it
}

但是,如果有一个Number子类没有提供,则它与原始方法有同样的问题Function。似乎在很多情况下这都没有用。

2020-11-16