Java – converts a list to a list (or any class that extends number)

I want to create a very general utility method to use any collection and convert it to a collection of user selectable classes extended from number (long, double, float, integer, etc.)

I came up with the code to use Google collections to convert the collection and return the immutable list

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);
    }

It can be used like this:

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

Does my code exceed the standard, or how can you simplify it while keeping it generic?

Solution

I think the most important aspect of this code is the function, not the method itself I also don't think it makes sense to switch the allowed subclasses in the function body, because you already know the number type to return when creating the function If given, for example, BigInteger Class, there is also a problem that your method fails

Given this, what I will do is to create a utility class (let's call it numbers) and provide methods. Each function returns a function (which can be an enumeration singleton) to resolve a string to a specific type of number That is:

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

Each of them can achieve this:

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";
  }
}

The user can then use it:

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

This method has many advantages over you:

>We don't need any switching in the function... We know what type of numbers we're creating, just do it Faster. > More flexible, because each function can be used anywhere. Users will not use it in your way (copy the transformed value to immutablelist) > you just need to create the functions you actually want to allow If there is no BigInteger parsing function, users can only call it, instead of completely legal at compile time, and then fail at run time, as in your example

As a note, I suggest that any method of return type that returns immutablelist is immutablelist instead of list... It provides useful information for the client of the method

Edit:

If you really need something more dynamic (that is, you want a class with some instances of class < T extensions number > to convert strings to this number type), you can also add a lookup method, such as:

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

This has the same problem as your original method, but if there is a number subclass that does not provide a function It doesn't seem to have many situations, which will be useful

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>