【问题标题】:Java 8 Streams modify collection valuesJava 8 Streams 修改集合值
【发布时间】:2015-03-09 12:31:30
【问题描述】:

使用流 API;过滤相关数据后,我想编辑正在收集的数据。到目前为止的代码如下:

  String wordUp = word.substring(0,1).toUpperCase() + word.substring(1);
  String wordDown = word.toLowerCase();

  ArrayList<String> text = Files.lines(path)
        .parallel() // Perform filtering in parallel
        .filter(s -> s.contains(wordUp) || s.contains(wordDown) &&  Arrays.asList(s.split(" ")).contains(word))
        .sequential()
        .collect(Collectors.toCollection(ArrayList::new));

编辑下面的代码很糟糕,我试图避免它。(它也不能完全工作。它是在凌晨 4 点完成的,请原谅。)

    for (int i = 0; i < text.size(); i++) {
        String set = "";
        List temp = Arrays.asList(text.get(i).split(" "));
        int wordPos = temp.indexOf(word);

        List<String> com1 = (wordPos >= limit) ? temp.subList(wordPos - limit, wordPos) : new ArrayList<String>();
        List<String> com2 = (wordPos + limit < text.get(i).length() -1) ? temp.subList(wordPos + 1, wordPos + limit) : new ArrayList<String>();
        for (String s: com1)
            set += s + " ";
        for (String s: com2)
            set += s + " ";
        text.set(i, set);
    }

它正在寻找文本文件中的特定单词,一旦过滤了该行,我希望每次只收集该行的一部分。正在搜索的关键字两侧的多个单词。

例如:

keyword = "the" limit = 1

它会找到:"Early in the morning a cow jumped over a fence."

然后它应该返回:"in the morning"

*附注任何建议的速度改进都将被投票。

【问题讨论】:

  • 我看不出你如何在代码中使用这个limit...
  • 要修改元素,请使用流的map方法。
  • 另外,如果keyword是句子中的第一个并且limit1,会发生什么?
  • wordUpwordDownword有什么区别?
  • 在同一个流上调用.parallel().sequential() 是没有意义的。流是并行的或顺序的。请注意,collect 与并行流完美配合。此外,您的状况x || y &amp;&amp; z 看起来很可疑;注意运算符的优先级。但目前还不清楚它应该做什么。

标签: java java-8 java-stream collectors


【解决方案1】:

您应该考虑两个不同的任务。首先,将文件转换为单词列表:

List<String> words = Files.lines(path)
    .flatMap(Pattern.compile(" ")::splitAsStream)
    .collect(Collectors.toList());

这使用了您在空格字符处拆分的最初想法。这对于简单的任务可能已经足够了,但是,您应该研究the documentation of BreakIterator 以了解这种简单方法与真正复杂的词边界分割之间的区别。

其次,如果你有一个单词列表,你的任务是找到你的 word 的匹配项,并通过使用单个空格字符作为分隔符连接单词,将匹配项周围的项目序列转换为单个匹配 String

List<String> matches=IntStream.range(0, words.size())
    // find matches
    .filter(ix->words.get(ix).matches(word))
    // create subLists around the matches
    .mapToObj(ix->words.subList(Math.max(0, ix-1), Math.min(ix+2, words.size())))
    // reconvert lists into phrases (join with a single space
    .map(list->String.join(" ", list))
    // collect into a list of matches; here, you can use a different
    // terminal operation, like forEach(System.out::println), as well
    .collect(Collectors.toList());

【讨论】:

  • 这个答案太棒了,它很优雅,正是我正在寻找的答案,非常感谢。我喜欢它避免了在逐行选择单词时可能出现的任何问题。我会看看你建议的链接。还有一件事,您是否有关于我如何找到此类事情的时间复杂度的链接或建议?
  • 我可能是错的,但我认为两者的时间复杂度都是 O(n),因为它们会遍历流中的所有 n 元素。但是,他们在一起会是O(n) + O(n) = O(2n)吗?
  • @Warosaurus 从技术上讲,O(2n) = O(n) ;-)
猜你喜欢
  • 2015-06-19
  • 1970-01-01
  • 2014-04-29
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 2018-05-10
  • 1970-01-01
相关资源
最近更新 更多