如何使用流(Stream)比较字符串字符?

4

在学习流编程时,我遇到了一个问题。我有一个列表,需要按照字符串的长度进行排序,其中所有包含大写字符的字符串都要匹配,如果没有这样的字符串,则按字母顺序排序。

List<String> phones = new ArrayList<>();
Collections.addAll(phones, "iPhone X", "Nokia 9", "Huawei Nexus 6P",
        "Samsung Galaxy S8", "LG G6", "Xiaomi MI6", "Sony Xperia Z5",
        "Asus Zenfone 3", "Meizu Pro 6", "Heizu Pro 6",
        "pixel 2");

phones.stream().filter(s -> s.matches("A-Z")).sorted(Comparator.comparingInt(String::length)).forEach(System.out::println);

我尝试使用matches,但似乎出了问题,因为没有任何输出。我该怎么解决?


  1. 您的筛选条件不太合适。
  2. 即使您进行筛选,也无法对剩余元素按字母顺序进行排序。您只对(1)感兴趣吗?
- Naman
你能否提供一个你期望的具体示例? - Nicholas K
2个回答

3

需要注意的是,您需要确保字符串有两个不同的分类,一个包含任何大写字母,另一个则没有。为此,您可以将列表分成以下两部分:

Map<Boolean, List<String>> partitionedValues = phones.stream()
        .collect(Collectors.partitioningBy(a -> containsUpperCase(a)));

containsUpperCase 的实现方式如下:

boolean containsUpperCase(String value) {
    for (char ch : value.toCharArray()) {
        if (Character.isUpperCase(ch)) {
            return true;
        }
    }
    return false;
}

一旦您将数据进行分区,您需要将这些数据聚合为单个最终列表,如下:

List<String> finalOutput = partitionedValues.get(Boolean.TRUE) // with upper case
        .stream()
        .sorted(Comparator.comparing(String::length)) // sorted by length
        .collect(Collectors.toList());

finalOutput.addAll(partitionedValues.get(Boolean.FALSE) // without uppercase
        .stream()
        .sorted(Comparator.naturalOrder()) // sorted naturally
        .collect(Collectors.toList()));

你的最终输出将会显示为:

finalOutput.forEach(System.out::println);

2
这段文字的翻译如下:
这个答案是关于正则表达式匹配部分的。 你正在匹配一个三个字符的序列 A-Z,因此没有任何一个字符串会匹配。
我试着解决你问题中的这一部分。 一个可能的模式是: .*[A-Z].* 你可以在这里检查它。

可能它可以被优化,但我认为现在它能够工作。 - Jónás Balázs
谢谢您的纠正。我在正则表达式上过于复杂了。 - Jónás Balázs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接