使用java 8 stream

时间:2018-05-31 00:04:22

标签: java java-8 java-stream

我有一个像这样的字符串列表"出租车或公共汽车司机"。我需要将每个单词的第一个字母转换为大写字母,除了单词"或" 。有没有简单的方法来使用Java流来实现这一点。 我尝试过使用Pattern.compile.splitasstream技术,我无法将所有分裂的标记连接起来形成原始字符串 如果有任何身体需要,我可以在这里发布我的代码。

4 个答案:

答案 0 :(得分:3)

您需要正确的模式来识别必须进行更改的位置,当您想要使用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

请注意,拆分时,无论是否符合条件,都会有第一个令牌。由于单词“or”通常不会出现在短语的开头,并且转换对非小写字母字符是透明的,因此这不应该是一个问题。否则,使用流特殊处理第一个元素会使代码过于复杂。如果这是一个问题,那么循环将更可取。

基于循环的解决方案可能看起来像

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)形式的方法引用替换lambda表达式ContainingClass::capitalizeWords

答案 1 :(得分:2)

这是我的代码:

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"));

    }
}

注意: 您可能还想查看有关使用apache commons-text library执行此工作的SO帖子。

答案 2 :(得分:1)

你可以这样做,

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());

答案 3 :(得分:1)

将字符串拆分为单词,然后将第一个字符转换为大写,然后将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(" "));