优先顺序输入比较

时间:2015-11-10 01:06:27

标签: java algorithm sorting java-8

如果给我一个包含多个可能短语的字符串,例如:

String input = "Cat, Dog, Rat";

是否有一种干净的方式(可能是枚举与地图结合?)来存储输入的优先顺序,以便我可以稍后按该顺序排序?我希望通过上面的输入对动物进行分类,因此Animal.type比较器将判断猫动物对大鼠的最后一只动物。什么是基于字符串解析输入和比较器如何使用它的顺序关联的简洁有效的方法?

1 个答案:

答案 0 :(得分:4)

这个怎么样?

String input = "Cat, Dog, Rat";
String[] arr = input.split(",\\s*");
Map<String, Integer> map = IntStream.range(0, arr.length).boxed().collect(Collectors.toMap(i -> arr[i], Function.identity()));
Comparator<String> comparator = Comparator.comparingInt(map::get);
List<String> list = Arrays.asList("Rat", "Rat", "Dog", "Dog", "Cat", "Rat");
list.sort(comparator);
System.out.println(list);

感谢@Holger指出您可以使用",\\s*"来改进此答案的原始版本,并且它意味着逗号后跟任意数量的空格字符。

此代码中最复杂的部分是行:

Map<String, Integer> map = IntStream.range(0, arr.length).boxed().collect(Collectors.toMap(i -> arr[i], Function.identity()));

我将尝试按步骤解释这里发生的事情。

  1. IntStream.range(0, arr.length)生成int的流: 012

  2. boxed()将此转换为Integer s:01的流, 2。我们需要Integer,因为您无法将int值放入 地图。

  3. 最后,我们收集这些值以生成地图{Cat=0, Dog=1, Rat=2}Collectors.toMap需要键映射器和值映射器。值映射器很简单,因为值只是流值012。这就是Function.identity()的含义:什么都不做。关键映射器通过执行i获取其中一个流值Cat并生成DogRatarr[i]。这就是lambda i -> arr[i]的含义。

  4. Streams,方法引用和lambdas需要一段时间才能掌握,但掌握它们是一个非常好的主意,因为有很多东西比Java 7中更容易表达。

    如果您只有极少数可能的字符串,那么使用地图可能会不必要地复杂化。您可以更简单地执行以下操作:

    String input = "Cat, Dog, Rat";
    List<String> animals = Arrays.asList(input.split(",\\s*"));
    Comparator<String> comparator = Comparator.comparingInt(animals::indexOf);
    List<String> list = Arrays.asList("Rat", "Rat", "Dog", "Dog", "Cat", "Rat");
    list.sort(comparator);
    System.out.println(list);
    

    请注意,如果存在大量可能的字符串,则使用indexOf并不是一个好主意,因为它会执行代价高昂的线性搜索。