Как функционально заменить цикл в цикле?

#java

#java

Вопрос:

У меня есть такой код:

  List<Account> myAccounts = new ArrayList<>();

 List<String> numbers = new ArrayList<>();

 List<Account> resultList = new ArrayList<>();

        for (String number : numbers) {
            for (Account account : myAccounts) {
                if(number.equals(account.getNumber())){
                    resultList.add(account);
                }
            }
        }
  

Я попытался получить определенные учетные записи с указанными номерами, но я делаю это через цикл all numbers и сравниваю с номерами учетных записей. Как я могу сделать это в функциональном стиле? Я спрашиваю не о том, как превратить это в функцию, а о том, как получить те же результаты, не выполняя каждый раз два цикла.

Комментарии:

1. Вы спрашиваете, как превратить это в функцию или как получить те же результаты без необходимости запускать два цикла каждый раз, когда вы хотите проверить?

2. @NathanWalsh без необходимости запускать два цикла каждый раз

3. вы можете использовать streams api. Пример: Список<Целое число> список = новый ArrayList<>(); list.stream().filter( i -> true ).forEach( i -> list.add(i)); Или вы даже можете заменить forEach на просто collect

4. @merc-angel Что ты подразумеваешь под «без необходимости запускать два цикла каждый раз»? Вы имеете в виду, что вам не нужно перебирать все элементы для каждого элемента? Потому что ответ Наги почти ничем не отличается от вашего вложенного цикла с точки зрения производительности. Единственное отличие заключается в том, что он не продолжается после того, как найдено совпадение, но вы можете легко поставить знак break «если», чтобы добиться этого.

Ответ №1:

 List<Account> myAccounts = new ArrayList<>();    
List<String> numbers = new ArrayList<>();    
List<Account> resultList = myAccounts.stream()
                .filter(account -> numbers.contains(account.getNumber()))
                .collect(Collectors.toList());
  

Вы можете использовать это. единственным требованием является то, что вы должны использовать как минимум Java8

Комментарии:

1. @merc-angel numbers , вероятно, должен быть a Set<String> , поскольку наборы обычно оптимизируют contains метод больше всего. Например, сложность HashSet#contiains близка к O(1).

2. 100% согласен с @Pshemo

Ответ №2:

Попробуйте сделать это так.

 List<Account> results = numbers.stream().flatMap(numb -> myAccounts
                  .stream()
                  .filter(acct->numb.equals(acct.getNumber()))
                  .collect(Collectors.toList());
  

Ответ №3:

Лучший способ добиться этого — загрузить объекты вашей учетной записи в базу данных sql lite. (Или добавьте его в свою текущую базу данных, если она у вас уже есть)

 https://developer.android.com/training/data-storage/sqlite
  

Затем, когда у вас есть все объекты учетной записи, хранящиеся в базе данных, вы можете просто написать запрос, чтобы перечислить учетные записи с соответствующими номерами.

Вот более полный пример того, как построить все, от создания базы данных до создания объектов и, в конечном итоге, запроса к ним.

 https://www.androidauthority.com/creating-sqlite-databases-in-your-app-719366/
  

Ответ №4:

При функциональном подходе вы бы создали метод из вашего цикла for, как в:

 public void compareNumbers(List<String> numbers, List<Account> resultList){
  for (String number : numbers) {
        for (Account account : myAccounts) {
            if(number.equals(account.getNumber())){
                resultList.add(account);
            }
   }
}
  

Комментарии:

1. Хорошо, но я имею в виду, как заменить цикл в цикле

2. Вы должны использовать циклы, иначе как вы собираетесь сравнивать значения?

3. Я думаю, что это можно сделать: D

4. Вы могли бы прочитать в lambda, если вам интересно. Но я не уверен, можете ли вы перебирать массивы с помощью lambda.

5. Streams api вот как, посмотрите на другие ответы. Он попросил функциональный подход, и это не работает.