-1

While following a Java course I was asked to convert a regular class to a generic one. I think I partially succeeded but can'f find a way to get it 100% right.

public class ElementUtils {
    public static <T> List transformedList(List<T> inList, Function<T, T> f) {
        List<T> outList = new ArrayList<>();
        for (T s : inList) {
            outList.add(f.apply(s));
        }
        return outList;
    }
}

Test class

public class Test {
    public static void main(String[] args) {
        List<String> lijst = Arrays.asList("Jan", "Jos", "Anna", "Pieter", "Johan");

        List<String> upCaseList = ElementUtils.transformedList(lijst, String::toUpperCase);
        List<String> replaceList = ElementUtils.transformedList(lijst, s -> s.replace("i", "IETS"));
        List<String> exclList = ElementUtils.transformedList(lijst, s -> s + "!");
        List<Integer> wordLengths = ElementUtils.transformedList(lijst, String::length);

        System.out.println(upCaseList);
        System.out.println(replaceList);
        System.out.println(exclList);
        System.out.println(wordLengths);
    }
}

When I remove the last statement wordLengths it works fine but throws a warning. With the last statement in it, it's telling ne that I cannot reference a method from a static content.

Error:

Error:(13, 49) java: method transformedList in class cvo.ex2.ElementUtils cannot be applied to given types;
  required: java.util.List<T>,java.util.function.Function<T,T>
  found: java.util.List<java.lang.String>,String::length
  reason: inference variable T has incompatible bounds
    equality constraints: java.lang.String
    lower bounds: java.lang.Integer

I don't understand what I'm missing here... Thank you for your help.

DarkLite1
  • 13,637
  • 40
  • 117
  • 214

2 Answers2

1

You provide the same generic type T for input and output. You need an input type T and a result type R, and also return a List of type R to get rid of the warning.

public static <T,R> List<T> transformedList(List<T> inList, Function<T, R> f) {
    List<R> outList = new ArrayList<>();
    for (T s : inList) {
        outList.add(f.apply(s));
    }
    return outList;
}
Rüdiger Schulz
  • 2,588
  • 3
  • 27
  • 43
  • Thank you, but Intellij tells me `cannot resolve symbol T` when I copy your code to test. – DarkLite1 Oct 06 '17 at 08:42
  • @DarkLite1 He introduced a new generic type which is wrong. You want to use the generic type of `T`. Updated his answer. – Murat Karagöz Oct 06 '17 at 08:48
  • Sorry, the result type must also be declared as well. I updated my answer. The edit by Murat is not solving your problem that your output type is not always the same as your input type (String in the first three examples, Integer in the fourth one) – Rüdiger Schulz Oct 06 '17 at 08:51
  • Thank you Rudiger, had to change it to `public static List transformedList(List inList, Function f) {` but now it's working perfect. Have to go over this a few times to fully understand it. – DarkLite1 Oct 06 '17 at 08:55
0

Basically < T> means a type but in one method call < T> must be the same everywhere. You cannot use < T> once as Integer and then with String in the same method invocation.

In this line: List < T> outList = new ArrayList<>();

What does < T> mean since once it has been Integer and once String in the same call. Java cannot guess ;)

Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23