преобразовать в заглавную букву, используя поток Java 8 - PullRequest
0 голосов
/ 31 мая 2018

У меня есть список строк, таких как «Такси или водитель автобуса».Мне нужно преобразовать первую букву каждого слова в заглавную букву, кроме слова «или».Есть ли простой способ добиться этого с помощью потока Java.Я пытался использовать технику Pattern.compile.splitasstream, но я не смог соединить все разделенные токены обратно, чтобы сформировать исходную строку, любая помощь будет оценена. Если понадобится любое тело, я могу опубликовать свой код здесь.

Ответы [ 4 ]

0 голосов
/ 31 мая 2018

Вам нужен правильный шаблон для определения местоположения , где необходимо внести изменение, - шаблона нулевой ширины, когда вы хотите использовать splitAsStream.Совпадение местоположений, которые

  • начало слова
  • глядя на строчные буквы
  • не глядя на слово «или»

Объявите это как

static final Pattern WORD_START_BUT_NOT_OR = Pattern.compile("\\b(?=\\p{Ll})(?!or\\b)");

Затем, используя его для обработки токенов, вы можете использовать поток с прямым потоком и map.Возвращение строки работает через .collect(Collectors.joining()):

List<String> input  = Arrays.asList("Taxi or bus driver", "apples or oranges");
List<String> result = input.stream()
    .map(s -> WORD_START_BUT_NOT_OR.splitAsStream(s)
        .map(w -> Character.toUpperCase(w.charAt(0))+w.substring(1))
        .collect(Collectors.joining()))
    .collect(Collectors.toList());
result.forEach(System.out::println);
Taxi or Bus Driver
Apples or Oranges

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

Решение на основе цикла может выглядеть как

private static final Pattern FIRST_WORD_CHAR_BUT_NOT_OR
                           = Pattern.compile("\\b(?!or\\b)\\p{Ll}");

(теперь используется шаблон, который соответствует символу, а не смотрит на него)

public static String capitalizeWords(String phrase) {
    Matcher m = FIRST_WORD_CHAR_BUT_NOT_OR.matcher(phrase);
    if(!m.find()) return phrase;
    StringBuffer sb = new StringBuffer();
    do m.appendReplacement(sb, m.group().toUpperCase()); while(m.find());
    return m.appendTail(sb).toString();
}

, который в качестве бонуса также способен обрабатывать персонажей, которые охватывают несколько char единиц.Начиная с Java 9, StringBuffer можно заменить на StringBuilder для повышения эффективности.Этот метод может использоваться как

List<String> result = input.stream()
    .map(s -> capitalizeWords(s))
    .collect(Collectors.toList());

Замена лямбда-выражения s -> capitalizeWords(s) на ссылку на метод в виде ContainingClass::capitalizeWords также возможна.

0 голосов
/ 31 мая 2018

Вы можете сделать это так,

final List<String> firstLetterCapitalized = driverOptions.stream().map(line -> Stream.of(line.split(" "))
        .map(token -> token.equals("or") ? token : Character.toUpperCase(token.charAt(0)) + token.substring(1))
        .collect(Collectors.joining(" "))).collect(Collectors.toList());
0 голосов
/ 31 мая 2018

Разделите вашу строку как слова, затем преобразуйте первый символ в верхний регистр, затем joining, чтобы сформировать оригинальную строку:

String input = "Taxi or bus driver";
String output = Stream.of(input.split(" "))
                .map(w -> {
                     if (w.equals("or") || w.length() == 0) {
                         return w;
                     }
                     return w.substring(1) + Character.toUpperCase(w.charAt(0));
                })
                .collect(Collectors.joining(" "));
0 голосов
/ 31 мая 2018

Вот мой код:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ConvertToCapitalUsingStreams {
    // collection holds all the words that are not to be capitalized
    private static final List<String> EXCLUSION_LIST = Arrays.asList(new String[]{"or"});

    public String convertToInitCase(final String data) {
        String[] words = data.split("\\s+");
        List<String> initUpperWords = Arrays.stream(words).map(word -> {
            //first make it lowercase
            return word.toLowerCase();
        }).map(word -> {
            //if word present in EXCLUSION_LIST return the words as is
            if (EXCLUSION_LIST.contains(word)) {
                return word;
            }

            //if the word not present in EXCLUSION_LIST, Change the case of
            //first letter of the word and return
            return Character.toUpperCase(word.charAt(0)) + word.substring(1);
        }).collect(Collectors.toList());

        // convert back the list of words into a single string
        String finalWord = String.join(" ", initUpperWords);

       return finalWord;
    }

    public static void main(String[] a) {
        System.out.println(new ConvertToCapitalUsingStreams().convertToInitCase("Taxi or bus driver"));

    }
}

Примечание. Вы также можете посмотреть этот пост SO об использовании библиотеки Apache commons-text для этой работы.

...