0

I already have this code implemented, and it works just fine:

static Integer[] parseInteger(String[] arr){
     return Arrays.stream(arr).map(Integer::parseInt).toArray(Integer[]::new);
}

But now I look for something like this:

public <T extends Number> T[] parseString(String[] arr,T n, Class<T> type){
    return Arrays.stream(arr).map(T::parseNumber).toArray(T[]::new);
}

Is there any solution for this problem? Didn't find anything.

Nicolas Filotto
  • 39,066
  • 11
  • 82
  • 105
koztantwo
  • 9
  • 1

2 Answers2

2

T::parseNumber won't work, since there is no parseNumber method in Number. Furthermore there is no inheritance for static methods. Also e.g. BigInteger doesn't even offer a static method for parsing from String and AtomicInteger doesn't offer a constructor that takes String, so even if you use reflection, you won't get it to work with the implementations of Number in the API, let alone all possible implementations...

T[]::new doesn't work since you cannot generate a array using a type parameter.

You could change the method to make it work however:

Pass a Function<String, T> to parse the Strings and either pass a IntFunction<T[]> to generate the array or use the Array class (see How to create a generic array in Java?):

public <T extends Number> T[] parseString(String[] arr, Function<String, T> parser, Class<T> type){
    return Arrays.stream(arr).map(parser).toArray(size -> (T[]) Array.newInstance(type, size));
}

Sample use

parseString(new String[]{ "1", "10", "193593118746464111646135179395251592"}, BigInteger::new, BigInteger.class)
Community
  • 1
  • 1
fabian
  • 67,623
  • 12
  • 74
  • 102
1

It cannot work because Number is an abstract class that doesn't provide any generic method allowing to parse a String into the corresponding Number implementation. You will need to provide your own method as next for example:

public class NumberParser {
    public static <T extends Number> T parseNumber(String val, Class<T> type) {
        if (type == Double.class) {
            return (T) Double.valueOf(val);
        } else if (type == Float.class) {
            return (T) Float.valueOf(val);
        } else if (type == Integer.class) {
            return (T) Integer.valueOf(val);
        } else if (type == Long.class) {
            return (T) Long.valueOf(val);
        }
        throw new IllegalArgumentException("Unknown number type");
    }
}

NB: This generic parser is not meant to be perfect, it just shows the idea.

Then your method will be:

public static <T extends Number> T[] parseString(String[] arr, Class<T> type){
    return Arrays.stream(arr).map(s -> NumberParser.parseNumber(s, type))
        .toArray(length ->  (T[]) Array.newInstance(type, length));
}

You will then be able to parse your array of String generically as next:

String[] values = {"1", "2", "3"};
Integer[] result = parseString(values, Integer.class);
for(Integer i : result) {
    System.out.println(i);
}

Output:

1
2
3
Nicolas Filotto
  • 39,066
  • 11
  • 82
  • 105