2015-10-31 5 views
2

Я ищу, чтобы заменить необходимость отдельных автономных статических инициализационных функций с lambdas. например Я хотел бы заменить что-то вроде этого ...В библиотеках JDK предоставляется класс лямбды 'invoker'?

class Foo { 
    private static final Set<String> keywords = keywords(); 

    private static Set<String> keywords() { 
     HashSet<String> s = new HashSet<>(); 
     s.add("AND"); 
     s.add("NOT"); 
     s.add("OR"); 
     return Collections.unmodifiableSet(s); 
    } 
} 

С чем-то, что вызывает лямбда, который определяется на месте во время загрузки класса. Обратите внимание, что это не моя цель, чтобы вызвать это лениво.

На данный момент я создал простой класс Initializer со статическим методом, который принимает Supplier, вызывает его и возвращает значение.

Initializer класс

public class Initializer { 
    public static <T> T init(Supplier<T> initializer) { 
     return initializer.get(); 
    }  
} 

Тогда в другом классе:

import static com.whatever.Initializer.init; 

class Foo { 
    private static final Set<String> keywords = init(() -> { 
     HashSet<String> s = new HashSet<>(); 
     s.add("AND"); 
     s.add("NOT"); 
     s.add("OR"); 
     return Collections.unmodifiableSet(s); 
    }); 
} 

Есть ли что-то, что существует в стандартных Java-библиотек уже, так что мне не нужно, чтобы обеспечить свой собственный Initializer класс, или есть какой-то способ просто определить, а затем выполнить лямбда на месте?

+1

Вам не нужен метод инициализации 'keywords'. Что такое точка вашей лямбда-версии? – zeroflagL

+1

Почему именно вам нужны лямбда? Похоже, вам нужен только статический блок инициализатора ('static {}') и вызывать свои inits там? – Zhedar

+0

Связанный: [Как инициализировать карту с помощью лямбда?] (Http://stackoverflow.com/questions/32868665/how-to-initialize-a-map-using-a-lambda) –

ответ

2

Вы можете просто бросить лямбда и назвать его:

private static final Set<String> KEYWORDS = ((Supplier<Set<String>>)() -> { 
    Set<String> result = new HashSet<>(); 
    ... 
    return Collections.unmodifiableSet(result); 
}).get(); 

Или вы могли бы использовать существующие ярлыки:

private static final Set<String> KEYWORDS = 
    Collections.unmodifiableSet(new HashSet<>(Arrays.asList("AND", "NOT", "OR"))); 

Но исходный код, вызов метода, очень читаемый. Я бы не изменил его.

+2

Для этого конкретного случая среди других , Я люблю коллекции Guava: 'KEYWORDS = ImmutableSet.of (« AND »,« NOT »,« OR »)' –

+0

Я до сих пор не получаю преимущества этого использования лямбда над обычным статическим инициализатором.Фактически, он даже не отличается от исходного подхода вопроса, поскольку код все еще находится внутри статического метода, теперь синтетического. Только способ, которым он вызван, имеет больше накладных расходов здесь. – Holger

+0

@ Хольгер Я согласен на 100%. Я просто хотел показать, что это возможно. Но, как говорится в моем ответе, я считаю, что исходный код более читабельен и не изменит его. –

1

Как указано в @zeroflagL, вам не нужно использовать лямбда в этом месте. Вы можете инициализировать keywords в одной строке с помощью:

Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("AND", "NOT", "OR"))); 

Но это не так красиво. В противном случае, что не так, используя блок static? Он был создан для таких вещей.

Но если вы не хотите его использовать, я думаю, что нет стандартного метода. Вы должны использовать свой Инициализатор.

2

Я хотел бы написать только специальный метод полезности, которая делает всю цепочку:

public class Sets { 
    public static <T> Set<T> of(T... elements) { 
     return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(elements))); 
    } 
} 

И использовать его там, где необходимо:

private static final Set<String> KEYWORDS = Sets.of("AND", "NOT", "OR"); 

Если случается использовать Guava, есть уже bunch of such methods. Надеемся, что такая функция появится в Java-9. Там JEP 269, который позволит написать Set.of("AND", "NOT", "OR").

+0

Хотя это полезно для коллекций, это не для других видов инициализации. – Bill

+1

@Bill, если «другой вид инициализации» (что бы это ни было) не может выполняться в одном выражении, возможно, он должен быть реорганизован. Рассмотрите возможность создания новых конструкторов, фабричных методов или реализации шаблона построителя. Я считаю, что гораздо лучше решить эту проблему для каждого случая, чем создать обобщенное решение, которое в любом случае является уродливым. –