将字符串拆分为列表,排序并保持顺序

Split string into list, sort and maintain order

我有一个用管道分隔的字符串,我想将它放到一个列表中并按相反的顺序对它进行排序。

但是我看到订单没有维护。这里有什么问题?

String str = "Chicago|Indianapolis|Boston|Houston";
List<String> splitList= Stream.of(str.split("\|"))
                .map(String::trim)
                .sorted(Collections.reverseOrder())
                .limit(30)
                .collect(toList());

//Expected [Houston,Boston,Indianapolis,Chicago]
//Got [Indianapolis,Houston,Boston,Chicago]

尝试以下

    String str = "Chicago|Indianapolis|Boston|Houston";
    List<String> splitList= Arrays.asList(str.split("\|"));
    Collections.reverse(splitList);
    System.out.println(splitList);

输出为:

[Houston, Boston, Indianapolis, Chicago]

您可以使用以下方式进行

String cityStr = "Chicago|Indianapolis|Boston|Houston";
List<String> cityList = Arrays.asList(cityStr.split("\|"))
.stream().sorted( Comparator.reverseOrder()).collect( Collectors.toList());

问题

您的代码是以相反的顺序对元素进行排序。因此,它保持反向排序顺序而不是它们在字符串中出现的顺序。

想法

您需要的Stream操作不会存储中间结果供您反转。您可以迭代元素并继续将它们添加到 Collection 的开头,这实际上颠倒了顺序。

List 与 Deque

ArrayListaddFirst(...)O(n^2)的时间。因此,请改用 Deque,这样可以有效地将元素添加到前面。

代码:

String str = "Chicago|Indianapolis|Boston|Houston";
Deque<String> splitList = Stream.of(str.split("\|"))
    .map(String::trim)
    .collect(Collector.of(
        ArrayDeque::new,
        (deq, t) -> deq.addFirst(t),
        (d1, d2) -> {
            d2.addAll(d1);
            return d2;
        }));
System.out.print(splitList);

输出:

[Houston, Boston, Indianapolis, Chicago]

专业提示:

在容量受限的环境下,可以使用方法offerFirst(...),只插入不违反容量限制的元素。将需要异常处理。