Java - Как использовать функции в потоке? - PullRequest
0 голосов
/ 14 мая 2019

Недавно, в рамках моих исследований, мы начали практиковать решение проблем Java с помощью потоков.При решении количественных задач сложения / вычитания или сортировки строк / символов с потоками, относительно ясных и понятных, однако, некоторые более сложные проблемы не ясны для меня с использованием потоков.

Например, учитываянабор символов, мы должны напечатать для каждой буквы в диапазоне GO / перейти обратный сигнал, например, A становится Z, а буква b становится y.

Например, предположим, что у нас была коллекция 'A',' k ',' p '-> После операции мы получим только p.

Используя простые функции, я смог решить проблему следующим образом:

public static char flipLetter(char c){
    int count = 7;
    if((int)c >= 72 && (int)c <= 78){
        for (int i = 72; i <= 78; i++) {
            if((int)c == i)
                return (char)((int)'Z' - count);
            count++;
        }
    }
    else{
        for (int i = 104; i <= 110; i++) {
            if((int)c == i)
                return (char)((int)'z' - count);
            count++;
        }
    }
    return c;
}
public static boolean isInRange(char c){
    return (((int)c >= 72 && (int)c <= 78) || ((int)c >= 104 && (int)c <= 110));

}
public static void inRange(char arr[]){
    for (int i = 0; i < arr.length; i++) {
        if(isInRange(arr[i])){
            System.out.print(flipLetter(arr[i])+" ");
        }
    }
}

IБуду рад получить помощь о том, как я могу использовать написанный мною код для его реализации с помощью потоков, или услышать другие отзывы.

Ответы [ 3 ]

1 голос
/ 14 мая 2019

Вы должны попытаться написать код, документирующий намерение читателя.Поэтому, когда задание включает условие «для каждой буквы в диапазоне GO / Go», не пишите код, такой как

public static boolean isInRange(char c) {
    return (((int)c >= 72 && (int)c <= 78) || ((int)c >= 104 && (int)c <= 110));
}

Запись

public static boolean isInRange(char c) {
    return c > 'G' && c < 'O' || c > 'g' && c < 'o';
}

, что сразу делает очевидным, чтоВы говорите о диапазоне «GO / go (эксклюзивный)», а не «HN / hn (включительно)», а не о ненужном использовании чисел Юникод / ​​ASCII вместо записи констант символов.Код все равно будет делать то же самое, но теперь вы можете распознать исходную задачу в нем.Приведения типов не нужны ни в одном из вариантов.

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

    if(c > 'G' && c < 'O') {
        return (char)('Z' - (c - 'A'));
    }
    if(c > 'G' && c < 'O') {
        return (char)('z' - (c - 'a'));
    }

, но когда мы используем это после того, как диапазон уже проверен, мы можем выразить намерение провести различие между прописными и строчными буквами напрямую, используя Character.isUpperCase(…) или Character.isLowerCase(…).

Кроме того, основные арифметические правила говорят нам, что 'Z' - (c - 'A') - это то же самое, что и ('Z' + 'A') - c, аналогично для варианта в нижнем регистре, поэтому код для двух случаев отличается только одним постоянным значением.

Помещение этих результатов в операцию Stream приводит к

public static void yourTask(char[] arr) {
    CharBuffer.wrap(arr).chars()
        .filter(c -> c >= 'H' && c <= 'N' || c >= 'h' && c <= 'n')
        .map(c -> (Character.isUpperCase(c)? 'A'+'Z': 'a'+'z') - c)
        .forEachOrdered(ch -> System.out.print((char)ch+" "));
}

(имя метода, например inRange, звучит как тест, поэтому вы должны придумать лучшее имя, описывающее, что метод на самом деле делает)

Обратите внимание, что здесь используется IntStream, поскольку в Java нет CharStream, что хорошо, как в Java, вычисления с использованием значений char в любом случае выполняются с использованием int.Только в заключительном операторе печати нам нужно выполнить приведение типа к char, чтобы установить правильную семантику, которая влияет на способ печати значения.

1 голос
/ 14 мая 2019

Вы можете сделать:

public static void inRange(char arr[]){
    IntStream.range(0, arr.length).mapToObj(i -> arr[i])
             .filter(letter -> isInRange(letter))
             .map(letter -> flipLetter(letter))
             .forEach(e -> System.out.print(e  + " "));
}

, который создаст Stream переданного Array, отфильтрует все, что не находится в диапазоне, вызовет метод flipLetter для каждой буквы, а затем напечатает каждое из

0 голосов
/ 14 мая 2019

Одним из решений для метода inRange() было бы следующее:

public static void inRange(char[] arr) {
    IntStream.range(0, arr.length)
            .mapToObj(i -> arr[i])
            .filter(YourClass::isInRange)
            .map(YourClass::flipLetter)
            .forEach(c -> System.out.print(c + " "));
}

Если вы хотите получить результат как String, вы можете использовать это:

public static void inRange(char[] arr) {
    String result = IntStream.range(0, arr.length)
            .mapToObj(i -> arr[i])
            .filter(YourClass::isInRange)
            .map(YourClass::flipLetter)
            .map(String::valueOf)
            .collect(Collectors.joining(" "));
    System.out.println(result);
}

Если у вас есть String в качестве входных данных, где вы получаете char[], просто передав его методу и используя string.chars() вместо IntStream.range(0, arr.length).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...