JavaRush /Java блог /Random UA /Досить писати цикли! Топ-10 найкращих методів для роботи ...
Джон Дориан
37 рівень

Досить писати цикли! Топ-10 найкращих методів для роботи з колекціями з Java 8

Стаття з групи Random UA
Що таке колекції і для чого вони потрібні, думаю, учням JavaRush не треба пояснювати. Однак після виходу 8-ої версії багато елементарних операцій, на які раніше йшло 6-7 рядків коду, були спрощені до мінімуму. Без зайвих передмов - топ-10 найкращих методів Java8 Collections Framework, які заощадять вам купу часу та місця! Досить писати цикли!  Топ-10 найкращих методів для роботи з колекціями з Java 8 - 1Всім привіт, друзі! Звичка, як відомо, — друга натура. І звикнувши писати for (int i = 0; i <......)переучуватися зовсім не хочеться (тим більше, що ця конструкція досить проста і зрозуміла). Проте, всередині циклів ми часто повторюємо одні й самі елементарні операції, повторення яких дуже хотілося б позбутися. З виходом Java8 Oracle вирішабо допомогти нам із цим. Нижче — 10 найкращих методів колекцій, які заощадять вам купу часу та коду

1. Iterable.forEach(Consumer <? super T> action)

Назва говорить сама за себе. Перебирає передану колекцію і виконує лямбда-вираз actionдля кожного її елемента.
List <Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
numbers.forEach(s -> System.out.print(s + " "));
1 2 3 4 5 6 7

2. Collection.removeIf(Predicate<? super E> filter)

Теж нічого складного. Метод перебирає колекцію і видаляє ті елементи, які відповідають filter.
List <Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
numbers.removeIf(s -> s > 5);
 numbers.forEach(s -> System.out.print(s + " "));
В один рядок видаляємо зі списку всі числа більше ніж 5.

3. Map.forEach(BiConsumer<? super K, ? super V> action)

Метод forEachпрацює як для класів, реалізують інтерфейс Collection, а й у Map.
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");
books.forEach((a,b) -> System.out.println("Название книги: " + a + ". Автор: " + b));
Название книги: Братья Карамазовы. Автор: Федор Достоевский
Название книги: Философия Java. Автор: Брюс Эккель
Название книги: Преступление и наказание. Автор: Федор Достоевский
Название книги: Война и мир. Автор: Лев Толстой
Название книги: Властелин Колец. Автор: Джон Толкин

4. Map.compute(K key,BiFunction<? super K, ?super V, ?extends V> remappingFunction)

Виглядає трохи страшніше, але насправді простий, як і всі попередні. Для зазначеного ключа keyцей метод встановлює як value результат виконання функції remappingFunction. Наприклад:
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");
books.forEach((a,b) -> System.out.println("Название книги: " + a + ". Автор: " + b));

books.compute("Философия Java", (a,b) -> b+", крутой чувак");
System.out.println("_______________________");
books.forEach((a,b) -> System.out.println("Название книги: " + a + ". Автор: " + b));
Название книги: Братья Карамазовы. Автор: Федор Достоевский
Название книги: Философия Java. Автор: Брюс Эккель
Название книги: Преступление и наказание. Автор: Федор Достоевский
Название книги: Война и мир. Автор: Лев Толстой
Название книги: Властелин Колец. Автор: Джон Толкин
_______________________
Название книги: Братья Карамазовы. Автор: Федор Достоевский
Название книги: Философия Java. Автор: Брюс Эккель, крутой чувак
Название книги: Преступление и наказание. Автор: Федор Достоевский
Название книги: Война и мир. Автор: Лев Толстой
Название книги: Властелин Колец. Автор: Джон Толкин
Автор " Філософії Java " безумовно крутий!:)

5. Map.computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

Метод додасть новий елемент у Map , але тільки в тому випадку, якщо елемент із таким ключем там відсутній. Як valueйому буде надано результат виконання функції mappingFunction. Якщо ж елемент із таким ключем вже є, він не буде перезаписаний, а залишиться на місці. Повернемося до наших книг і випробуваємо новий метод:
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");

books.computeIfAbsent("Гарри Поттер и узник Азкабана", b -> getHarryPotterAuthor());
books.forEach((a,b) -> System.out.println("Название книги: " + a + ". Автор: " + b));
Наша функція mappingFunction:
public static String getHarryPotterAuthor() {
        return "Джоан Роулинг";
    }
А ось і нова книга:
Название книги: Братья Карамазовы. Автор: Федор Достоевский
Название книги: Философия Java. Автор: Брюс Эккель
Название книги: Преступление и наказание. Автор: Федор Достоевский
Название книги: Война и мир. Автор: Лев Толстой
Название книги: Гарри Поттер и узник Азкабана. Автор: Джоан Роулинг
Название книги: Властелин Колец. Автор: Джон Толкин

6. Map.computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

Той самий принцип, що й у Map.compute(), але всі обчислення будуть виконані лише у випадку, якщо елемент із ключем keyвже існує.
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");

books.computeIfPresent("Евгений Онегин", (a,b) -> b="Александр Пушкин");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Название книги: " + a + ". Автор: " + b));
books.computeIfPresent("Братья Карамазовы", (a,b) -> b="Александр Пушкин");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Название книги: " + a + ". Автор: " + b));
При першому виклику функції жодних змін не відбулося, тому що книги з назвою "Євген Онєгін" у нашій Mapнемає. А ось вдруге програма змінила автора для книги "Брати Карамазови" на "Олександр Пушкін". Висновок:
_________________
Название книги: Братья Карамазовы. Автор: Федор Достоевский
Название книги: Философия Java. Автор: Брюс Эккель
Название книги: Преступление и наказание. Автор: Федор Достоевский
Название книги: Война и мир. Автор: Лев Толстой
Название книги: Властелин Колец. Автор: Джон Толкин
_________________
Название книги: Братья Карамазовы. Автор: Александр Пушкин
Название книги: Философия Java. Автор: Брюс Эккель
Название книги: Преступление и наказание. Автор: Федор Достоевский
Название книги: Война и мир. Автор: Лев Толстой
Название книги: Властелин Колец. Автор: Джон Толкин

7. Map.getOrDefault(Object key, V defaultValue)

Повертає значення, що відповідає ключу key. Якщо такого ключа немає — повертає значення за замовчуванням.
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");

String igor = books.getOrDefault("Слово о полку Игореве", "Неизвестный автор");
System.out.println(igor);
Дуже зручно:
Неизвестный автор

8. Map.merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

Я навіть не намагався порахувати, скільки рядків коду вам заощадить цей метод.
  • Якщо у вашому Mapключі keyне існує, або valueдля цього ключа одно null- метод додає в Mapпередану пару key-value.
  • Якщо ключ Keyіснує і його value != null– метод змінює його valueна результат виконання переданої функції remappingFunction.
  • Якщо remappingFunctionповертає nullkeyвидаляється з колекції.
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");

books.merge("Философия Java", "Брюс Эккель", (a, b) -> b +  " и кто-то там еще");
books.forEach((a,b) -> System.out.println("Название:" + a + ". Автор: " + b));
Висновок:
Название:Братья Карамазовы. Автор: Федор Достоевский
Название:Философия Java. Автор: Брюс Эккель и кто-то там еще
Название:Преступление и наказание. Автор: Федор Достоевский
Название:Война и мир. Автор: Лев Толстой
Название:Властелин Колец. Автор: Джон Толкин
*вибач, Брюс*

9. Map.putIfAbsent(K key, V value)

Раніше щоб додати пару до Map, якщо її там немає, необхідно було робити таке:
Map <String, String> map = new HashMap<>();
if (map.get("Властелин Колец") == null)
    map.put("Властелин Колец", "Джон Толкин");
Тепер все стало набагато простіше:
Map<String, String> map = new HashMap<>();
map.putIfAbsent("Властелин Колец", "Джон Толкин");

10. Map.replace та Map.replaceAll()

Останні за списком, але не за значимістю. Map.replace(K key, V newValue— замінює значення ключа keyна newValue, якщо такий ключ існує. Якщо ні – нічого не відбувається. Map.replace(K key, V oldValue, V newValue)- робить те саме, але тільки якщо поточне значення keyдорівнює oldValue. Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)— замінює всі значення valueна результат виконання функції function. Наприклад:
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");

books.replace("Братья Карамазовы", "Брюс Эккель", "Джон Толкин");
books.forEach((a,b) -> System.out.println("Название:" + a + ". Автор: " + b));
Название:Братья Карамазовы. Автор: Федор Достоевский
Название:Философия Java. Автор: Брюс Эккель
Название:Преступление и наказание. Автор: Федор Достоевский
Название:Война и мир. Автор: Лев Толстой
Название:Властелин Колец. Автор: Джон Толкин
Чи не спрацювало! Поточне значення ключа "Брати Карамазови" - "Федор Достоєвський", а не "Брюс Еккель", тому нічого не змінилося.
Map <String, String> books = new HashMap<>();
books.put("Война и мир", "Лев Толстой");
books.put("Преступление и наказание", "Федор Достоевский");
books.put("Философия Java", "Брюс Эккель");
books.put("Братья Карамазовы", "Федор Достоевский");
books.put("Властелин Колец", "Джон Толкин");

books.replaceAll((a,b) -> getCoolWriter());
books.forEach((a,b) -> System.out.println("Название:" + a + ". Автор: " + b));
public static String getCoolWriter() {
        return "Крутой писатель";
    }
Название:Братья Карамазовы. Автор: Крутой писатель
Название:Философия Java. Автор: Крутой писатель
Название:Преступление и наказание. Автор: Крутой писатель
Название:Война и мир. Автор: Крутой писатель
Название:Властелин Колец. Автор: Крутой писатель
Легко змінабо значення для всієї Map без жодних складних конструкцій! PS Звикати до нового завжди непросто, але ці зміни справді гарні. Принаймні деякі шматки мого коду тепер виразно менше схожі на спагетті, ніж раніше:) Якщо вам сподобалася стаття, і ви хотіли б побачити нові - не забудьте підтримати автора в конкурсі, натиснувши "Подобається", а краще - "Дуже подобається" :) Успіхів у навчанні!
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ