Как сравнить и управлять двумя смежными элементами в одном списке, используя поток в Java? - PullRequest
0 голосов
/ 21 января 2019

Фон у меня есть две переменные типа String str1 и str2 в качестве входных данных. Наконец я должен вернуть список, который содержит последовательный префикс str1, который меньше соответствующего префикса в str2.

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

public List<Character> getPrefix(String str1, String str2) {
    int index = 0;
    List<Character> res = new ArrayList<>();
    //str1 = "1243"
    //str2 = "2324"
    // The answer will be "12".

    while (index < str1.length() && index < str2.length() && str1.charAt(index) <= str2.charAt(index)) {
        res.add(str1.charAt(index));
        index++;
    } 

    return res;
}
//the return type could either be List<String> or List<Character>

Меня попросили преобразовать этот код в поток без использования цикла while или for, просто в методе stream. Я планирую конвертировать этот код следующим образом

List<String> list = new ArrayList<>();
list.add(str1);
list.add(str2);
List<String> res = list.stream()
.filter()
.reduce();

Я обнаружил, что метод filter() может выбрать элемент, который соответствует данному предикату, а метод reduce() может использовать идентификатор и аккумулятор для получения одного окончательного результата.

Но я обнаружил, что у меня не было ни способа управлять двумя смежными элементами в одном списке, ни получить один указатель для сравнения и прохождения каждого символа в каждом элементе в списке (элемент имеет тип String).

Так есть ли способы, которыми я мог бы управлять двумя смежными элементами в одном списке, чтобы я мог сравнить их символы, которые находятся в одной и той же позиции.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Вы можете:

  1. Генерация потока индексов
  2. Получить символы обеих строк, используя индекс
  3. Выберите символы действительны

    // The magic
    public static List<Character> getPrefix(String str1, String str2) {
    
        return IntStream
            .range(0, Math.min(str1.length(), str2.length()))
            .mapToObj(i -> new char[] { str1.charAt(i), str2.charAt(i) })
            .takeWhile(a -> a[0] < a[1])
            .map(a -> a[0])
            .collect(Collectors.toList());
    
    }
    
0 голосов
/ 21 января 2019

Посмотрите на код и, возможно, это то, что вы хотите. Тем не менее, это может быть улучшено больше и не решить случай, когда первая строка начинается со значения больше, чем вторая. Это также может быть реализовано, но требует дополнительной работы. (не удалось сделать одним куском, потому что поставщик потребляет один элемент для проверки, необходимой для цепочки dropWhile и takeWhile). Просто с поставщиком вы можете сравнить элементы из потока с элементами из другой структуры данных.

import java.util.LinkedList;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class Pre1 {

    public static void main(String[] args) {
        System.out.println(new Pre1().getPre("1234", "2315"));
        System.out.println(new Pre1().getPre("941234", "712315"));
        System.out.println(new Pre1().getPre("2345", "341"));   
    }

    public String getPre(String s1, String s2) {
        //second list is used as supplier
        LinkedList<Integer> l2 = s2.chars().boxed()
            .map(t->Character.getNumericValue(t))
            .collect(Collectors.toCollection(LinkedList<Integer>::new));
        //l2.forEach(System.out::println);
        Supplier<Integer> supplier = () -> {
        //   System.out.println(l2.peek());
             return l2.isEmpty() ? 0 : l2.pollFirst();
        };

        return s1.chars().boxed()
             .map(t->Character.getNumericValue(t))
             .takeWhile(t->t<supplier.get())
             .map(t->String.valueOf(t))
             .collect(Collectors.joining());
    }
}

выход

12
nothing 
23
...