Эффективный обзор Java (Серия из 79 частей)
С появлением лямбд как части языка Java открылось больше возможных реализаций. Там, где раньше мы могли использовать альтернативный шаблон, такой как, возможно, шаблон метода шаблона , где подкласс переопределяет метод для специализации поведения суперкласса, теперь мы можем использовать фабричный метод, который принимает лямбду, которая служит функцией специализации.
Давайте посмотрим на другой пример, Связанная хэш – карта . Это может служить кэшем, переопределяя removeEldestEntry , который вызывается при каждой операции put с самым старым элементом и который, когда он возвращает true , удаляет самую старую запись. Например, если бы мы хотели ограничить нашу карту 100 записями, мы могли бы написать что-то вроде:
protected boolean removeEldestEntry(Map.Entryeldest) { return size() > 100; }
Этот метод отлично работает но если бы он был построен сегодня, возможно, было бы чище передать лямбду для достижения этой цели. Итак, давайте подумаем, что нужно сделать для этой карты. Это, конечно, заняло бы Карту. Запись точно такая же, как у нас removeEldestEntry метод. Ему также нужна ссылка на саму карту, так как она вызывает метод size . Наконец, нам нужно рассмотреть тип возвращаемого значения, который в данном случае будет логическим . Итак, собрав все это вместе, мы получили бы:
@FunctionalInterface interface EldestEntryRemovalFunction{ boolean remove(Map map, Map.Entry eldest); }
Этот интерфейс будет отлично работать, это именно то, что нам нужно. Вопрос в том, необходимо ли это? Java предоставляет нам сорок три функциональных интерфейса в пакете java.util.function , который охватывает множество вариантов использования. Я не думаю, что кто-то ожидает, что вы запомните все интерфейсы, но есть определенные строительные блоки, которые, если мы поймем, мы сможем определить, какие интерфейсы нам доступны.
Давайте погрузимся в эти строительные блоки. Существует пять основных классов функциональных интерфейсов. Оператор интерфейсы (которые существуют Унарные и Двоичные версии, которые принимают один и два аргумента соответственно), которые принимают и возвращают один и тот же тип аргумента. Предикат , который принимает аргумент и возвращает логическое значение . Функция какие аргументы и тип возвращаемого значения различаются. Поставщик который не принимает аргументов и возвращает значение. Потребитель который принимает аргументы и ничего не возвращает.
Существует три варианта каждого из них , которые работают с int , long и double , например Предикат Int , который принимает int и возвращает логическое значение . У нас также есть Функция интерфейсы, которые преобразуют из одного примитивного типа в другой по шаблону, например Src В результат например Функция longtointфункция . Если источником является примитив, а результатом является объект, мы будем следовать шаблону SrcToObj , , например Двойная функция
Это должно дать вам представление о возможностях, когда вы хотите использовать интерфейс. Суть этой главы состоит в том, чтобы побудить вас использовать эти стандартные интерфейсы вместо того, чтобы просто создавать свои собственные. Используя эти стандартные интерфейсы, вы используете то, с чем люди будут более знакомы, вам потребуется меньше кода для управления, а встроенные типы содержат полезные методы, которые вы можете использовать, такие как объединение предикатов вместе.
Еще одна вещь, на которую следует обратить внимание: из всех этих интерфейсов, созданных для нас, основная часть предназначена для использования примитивов без упаковки и распаковки. Учитывая все это, предоставленное нам, нет причин использовать коробочные типы вместо примитивов.
Итак, когда мы должны создавать наши собственные функциональные интерфейсы? Есть несколько случаев, когда вы захотите создать свои собственные интерфейсы. Первый случай наиболее очевиден: если ни один из интерфейсов не соответствует вашим требованиям, создайте свой собственный. Другой случай – это когда имеет смысл сделать более описательное название, а также если оно будет использоваться во многих местах для обозначения определенной вещи.
Таким образом, при использовании лямбд сначала рассмотрите возможность использования одного из встроенных функциональных интерфейсов, а не создания собственного.
Эффективный обзор Java (Серия из 79 частей)
Оригинал: “https://dev.to/kylec32/effective-java-favor-the-use-of-standard-functional-interfaces-4gem”