1. Общ преглед
Намирането на елемент в списък е много често срещана задача, която срещаме като разработчици.
В този бърз урок ще разгледаме различни начини, по които можем да направим това с Java.
2. Настройка
Първо нека започнем с дефиниране на POJO на клиента :
public class Customer { private int id; private String name; // getters/setters, custom hashcode/equals }
След това ArrayList от клиенти:
List customers = new ArrayList(); customers.add(new Customer(1, "Jack")); customers.add(new Customer(2, "James")); customers.add(new Customer(3, "Kelly"));
Имайте предвид, че сме заменили hashCode и се равняваме в нашия клас Customer .
Въз основа на текущата ни реализация на equals , два обекта на Клиент с един и същ идентификатор ще се считат за равни.
Ще използваме този списък с клиенти по пътя.
3. Използване на Java API
Самата Java предоставя няколко начина за намиране на елемент в списък:
- В съдържа метод
- В indexOf Метод
- Ad-hoc за цикъл
- The Stream API
3.1. съдържа()
Списък излага метод, наречен съдържа :
boolean contains(Object element)
Както подсказва името, този метод връща true, ако списъкът съдържа посочения елемент, и връща false в противен случай.
Така че, когато трябва да проверим дали даден елемент съществува в нашия списък, можем:
Customer james = new Customer(2, "James"); if (customers.contains(james)) { // ... }
3.2. индекс на()
indexOf е друг полезен метод за намиране на елементи:
int indexOf(Object element)
Този метод връща индекса на първото появяване на посочения елемент в дадения списък или -1, ако списъкът не съдържа елемента .
Така че логично, ако този метод връща нещо различно от -1, знаем, че списъкът съдържа елемента:
if(customers.indexOf(james) != -1) { // ... }
Основното предимство на използването на този метод е, че той може да ни каже позицията на посочения елемент в дадения списък.
3.3. Основен цикъл
Ами сега, ако искаме да направим полево търсене на елемент? Например, да кажем, че обявяваме лотария и трябва да обявим Клиент с конкретно име за победител.
За такива полеви търсения можем да се обърнем към итерация.
Традиционен начин за итерация през списък е използването на една от цикличните конструкции на Java. Във всяка итерация сравняваме текущия елемент в списъка с елемента, който търсим, за да видим дали съвпада:
public Customer findUsingEnhancedForLoop( String name, List customers) { for (Customer customer : customers) { if (customer.getName().equals(name)) { return customer; } } return null; }
Тук името се отнася до името, което търсим в дадения списък с клиенти . Този метод връща първия обект на клиента в списъка със съответстващо име или null, ако такъв клиент не съществува.
3.4. Циклиране с итератор
Итераторът е друг начин, по който можем да обходим списък с елементи.
Можем просто да вземем предишния си пример и да го променим малко:
public Customer findUsingIterator( String name, List customers) { Iterator iterator = customers.iterator(); while (iterator.hasNext()) { Customer customer = iterator.next(); if (customer.getName().equals(name)) { return customer; } } return null; }
Следователно поведението е същото като преди.
3.5. API на Java 8 Stream
От Java 8 също можем да използваме API на потока, за да намерим елемент в списък.
За да намерим елемент, отговарящ на конкретни критерии в даден списък, ние:
- извикайте stream () в списъка
- извикайте метода f ilter () с подходящ предикат
- извиква конструкцията findAny () , която връща първия елемент, който съвпада с предиката на филтъра, увит в Незадължителен, ако такъв елемент съществува
Customer james = customers.stream() .filter(customer -> "James".equals(customer.getName())) .findAny() .orElse(null);
За удобство по подразбиране нулираме, в случай че даден незадължителен е празен, но това не винаги може да бъде най-добрият избор за всеки сценарий.
4. Библиотеки на трети страни
Now, while the Stream API is more than sufficient, what should we do if we're stuck on an earlier version of Java?
Fortunately, there are many third-party libraries like Google Guava and Apache Commons which we can use.
4.1. Google Guava
Google Guava provides functionality that is similar to what we can do with streams:
Customer james = Iterables.tryFind(customers, new Predicate() { public boolean apply(Customer customer) { return "James".equals(customer.getName()); } }).orNull();
Just like with Stream API, we can optionally choose to return a default value instead of null:
Customer james = Iterables.tryFind(customers, new Predicate() { public boolean apply(Customer customer) { return "James".equals(customer.getName()); } }).or(customers.get(0));
The above code will pick the first element in the list if no match is found.
Also, don't forget that Guava throws a NullPointerException if either the list or the predicate is null.
4.2. Apache Commons
We can find an element in almost the exact same way using Apache Commons:
Customer james = IterableUtils.find(customers, new Predicate() { public boolean evaluate(Customer customer) { return "James".equals(customer.getName()); } });
Има няколко важни разлики обаче:
- Apache Commons просто връща null, ако предадем нулев списък.
- Тоне предоставя функционалност на стойността по подразбиране като tryFind на Guava.
5. Заключение
В тази статия научихме различни начини за намиране на елемент в списък, като се променя с бързи проверки на съществуването и завършва с полеви търсения.
Също така разгледахме библиотеките на трети страни Google Guava и Apache Commons като алтернативи на API 8 Streams API.
Благодарим ви, че се отбихте и не забравяйте да проверите всички източници за тези примери на GitHub.