4

I'm used to declaring array inline like this:

    String s1 = "world";
    String[] strings = { "world" };

Why can't I do the same for functions? Given I have a class Book with getTitle() and getAuthor() methods, this is valid:

    Function<Book, String> f1 = Book::getTitle;
    System.out.println(f1.apply(myBook));

However this is not:

    Function<Book, String>[] funcs = { Book::getTitle, Book::getAuthor };
    for (Function<Book, String> f2 : funcs) {
        System.out.println(f2.apply(myBook));
    }

It doesn't like the inline array declaration and the compiler error is "Cannot create a generic array of Function"

Edit I'd argue my question isn't a duplicate of the suggestion as I want to statically define a set of functions using the array initializer syntax

6
  • Try with a map, like this Map<String, Function<Book, String>> mapToFunctions = new HashMap<>(); Commented Jan 29, 2018 at 15:49
  • If is a generic type, you need to use funcs = new Function<Book, String>[] { Book::getTitle }; Commented Jan 29, 2018 at 15:51
  • @Héctor that gives the same error Commented Jan 29, 2018 at 16:02
  • Function[] funcs = { (Function<Book, String >) Book::getTitle };. Commented Jan 29, 2018 at 16:16
  • If you want to simply apply the same method call to all of your books(assuming books is a List), you can simply do List<String> titles = books.stream().map(Book::getTitle).collect(Collectors.toList()); and then titles.stream().forEach(System.out::println); to print them. It is redundant to create an array of the same function. Commented Jan 29, 2018 at 19:26

1 Answer 1

2

You could try this:

public static void testFunction() {
    Map<String, Function<Book, String>> mapToFunctions = new HashMap<>();

    Function<Book, String> myFunction = x -> new String(x.getTitle());

    mapToFunctions.put("firstfunction", myFunction);

    for (Function<Book, String> f : mapToFunctions.values()) {
        System.out.println(f.apply(new Book("my title")));
    }
}

UPDATE:

Using Set<Function<Book, String>> it would be something like:

package com.victor.main;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;

public class FunctionalTest {
    public static void testFunction() {
        Set<Function<Book, String>> mapToFunctions = new HashSet<>();

        Function<Book, String> myFunction = x -> new String(x.getTitle());

        mapToFunctions.add(myFunction);

        for (Function<Book, String> f : mapToFunctions) {
            System.out.println(f.apply(new Book("my title")));
        }
    }

    public static void main(String[] args) {
        testFunction();
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

That will get difficult to maintain when there are many functions, as you have to give them a name and a lambda. I really want a simple list.
Try with a Set<Function<Book, String>> funSet = new HashSet<>();
I updated the answer with a version using Set<Function<Book, String>>
Thanks. Looks like this falls into the category of "not possible because of type erasure"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.