CodeGym /Java блог /Случаен /Спрете да пишете цикли! 10 най-добри практики за работа с...
John Squirrels
Ниво
San Francisco

Спрете да пишете цикли! 10 най-добри практики за работа с колекции в Java 8

Публикувано в групата
Спрете да пишете цикли!  10 най-добри практики за работа с колекции в Java 8 - 1 Както знаете, нашите навици са втора природа. И след като свикнете да пишете for (int i = 0; i <......), никоя част от вас не иска да учи отново тази конструкция (особено след като е доста проста и разбираема). Въпреки това, циклите често се използват многократно за извършване на едни и същи основни операции и повторението е нещо, от което много бихме искали да се отървем. С Java 8 Oracle реши да ни помогне да направим това. По-долу са 10-те най-добри метода за събиране, които ще ви спестят много време и code.

1. Iterable.forEach(Consumer <? Super T> действие)

Името говори само за себе си. Той итерира колекцията, предадена като аргумент, и изпълнява действието ламбда израз за всеки от нейните елементи.

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(предикат<? супер E> филтър)

Отново няма нищо трудно тук. Методът итерира колекцията и премахва всички елементи, които съвпадат 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> действие)

Методът forEachработи не само за класове, които имплементират интерфейса Collection, но и за Map.

 Map <String, String> books = new HashMap<>();
 books.put("War and Peace", "Leo Tolstoy");
 books.put("Crime and Punishment", "Fyodor Dostoevsky");
 books.put("Thinking in Java", "Bruce Eckel");
 books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
 books.put("The Lord of the Rings", "John Tolkien");
 books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));

Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien

4. Map.compute (клавиш K, BiFunction<? Super K,? Super V,? Extends V> remappingFunction)

Изглежда малко по-страшно, но всъщност просто, като всички предишни. Този метод задава keyстойност равна на резултата от изпълнението mappingFunction. Например:

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
 
books.compute("Thinking in Java", (a,b) -> b + ", cool dude");
System.out.println("_______________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));

Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
_______________________
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel, cool dude
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
Authorът на "Thinking in Java" определено е готин! :)

5. Map.computeIfAbsent(клавиш K, функция <? super K, ? разширява V> mappingFunction)

Този метод ще добави нов елемент към Map, но само ако вече няма елемент с този ключ. Присвоената стойност ще бъде резултатът от изпълнението на mappingFunction. Ако елемент с ключ вече съществува, той няма да бъде презаписан. Просто ще си остане Howто е. Нека се върнем към нашите книги и да опитаме нов метод:

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.computeIfAbsent("Harry Potter and the Prisoner of Azkaban", b -> getHarryPotterAuthor());
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
Ето го нашия mappingFunction:

public static String getHarryPotterAuthor() {
        return "Joanne Rowling";
    }
А ето и новата книга:

Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Harry Potter and the Prisoner of Azkaban. Author: Joanne Rowling
Book title: Lord of the Rings. Author: John Tolkien

6. Map.computeIfPresent(ключ K, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

Тук имаме същия принцип като Map.compute(), но изчисленията се извършват само ако елемент с keyвече съществува.

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.computeIfPresent("Eugene Onegin", (a,b) -> b = "Alexander Pushkin");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
books.computeIfPresent("The Brothers Karamazov", (a,b) -> b = "Alexander Pushkin");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
Първото извикване на функцията не направи промени, защото в нашия няма книга със заглавие "Евгений Онегин" Map. Но във второто обаждане програмата промени автора на книгата "Братя Карамазови" на Александър Пушкин. Изход:

_________________
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
 _________________
Book title: The Brothers Karamazov. Author: Alexander Pushkin
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien

7. Map.getOrDefault(обектен ключ, V defaultValue)

Този метод връща стойността, съответстваща на key. Ако ключът не съществува, той връща стойността по подразбиране.

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
String igor = books.getOrDefault("The Tale of Igor's Campaign", "Unknown author");
System.out.println(igor);
Това е много удобно:

Unknown author

8. Map.merge(ключ K, V стойност, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

Дори не си направих труда да изчисля колко реда code ще ви спести този метод.
  1. Ако keyне съществува във вашия Mapor ако valueза този ключ е null, тогава методът добавя предадената key-valueдвойка към Map.
  2. Ако keyсъществува и е value != null, тогава методът променя стойността си на резултата от изпълнението remappingFunction.
  3. Ако remappingFunctionсе върне null, тогава keyсе премахва от колекцията.

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.merge("Thinking in Java", "Bruce Eckel", (a, b) -> b + " and some coauthor");
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));
Изход:

Title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Title: Thinking in Java. Author: Bruce Eckel and some coauthor
Title: Crime and Punishment. Author: Fyodor Dostoevsky
Title: War and Peace. Author: Leo Tolstoy
Title: Lord of the Rings. Author: John Tolkien
*съжалявам, Брус*

9. Map.putIfAbsent(ключ K, V стойност)

Преди, за да добавите чифт към Map, ако все още не е бил там, трябваше да направите следното:

Map <String, String> map = new HashMap<>();
if (map.get("Lord of the Rings") == null)
    map.put("Lord of the Rings", "John Tolkien");
Сега всичко стана много по-лесно:

Map<String, String> map = new HashMap<>();
map.putIfAbsent("Lord of the Rings", "John Tolkien");

10. Map.replace и Map.replaceAll()

Не на последно място.
  1. Map.replace(K key, V newValue)заменя keyстойността на с newValue, ако съществува такъв ключ. Ако не, нищо не се случва.
  2. Map.replace(K key, V oldValue, V newValue)прави същото, но само ако текущата стойност за keyе равна на oldValue.
  3. Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)замества всеки valueс резултат от функция.
Например:

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.replace("The Brothers Karamazov", "Bruce Eckel", "John Tolkien");
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));

Title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Title: Thinking in Java. Author: Bruce Eckel
Title: Crime and Punishment. Author: Fyodor Dostoevsky
Title: War and Peace. Author: Leo Tolstoy
Title: Lord of the Rings. Author: John Tolkien
Не се получи! Текущата стойност за ключа "Братя Карамазови" е "Фьодор Достоевски", а не "Брус Екел", така че нищо не се е променило.

Map  books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.replaceAll((a,b) -> getCoolAuthor());
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));

public static String getCoolAuthor() {
        return "Cool author";
     }

Title: The Brothers Karamazov. Author: Cool author
Title: Thinking in Java. Author: Cool author
Title: Crime and Punishment. Author: Cool author
Title: War and Peace. Author: Cool author
Title: Lord of the Rings. Author: Cool author
Лесно променихме стойностите за цялото Mapбез ниHowви сложни конструкции! PS Свикването с новото винаги е трудно, но тези промени са наистина добри. Във всеки случай, някои части от codeа ми определено не прorчат на спагети от преди :) Успех в ученето!
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION