【问题标题】:Check if 2D LinkedHashSet contains a specific string检查 2D LinkedHashSet 是否包含特定字符串
【发布时间】:2020-04-17 02:10:59
【问题描述】:

我正在尝试查找是否在我创建的 2D LinkedHashSet 中找到了特定的字符串值。

下面是一些初始化LinkedHashSet的代码:

LinkedHashSet<LinkedHashSet<String>> block = new LinkedHashSet<LinkedHashSet<String>>();

我曾尝试使用 .contains 像这样,但它似乎是一个不正确的参数类型:

  int N = Integer.parseInt(b1.readLine());
            for(int i = 0; i<N; i++) {
                String sorts [] = (b1.readLine()).split(" ");
                if(block.stream().anyMatch(list->list.contains(sorts[0]))) {
                    //System.out.println("I entered");
                    for (Set<String> innerSet : block) {
                        for (String string : innerSet) {
                            if(string.equals(sorts[0])) {
                                innerSet.add(sorts[5]);
                            }
                            if(string.equals(sorts[5])) {
                                innerSet.add(sorts[0]);
                            }
                        }
                    }
                }
                else {
                    block.add(new LinkedHashSet<String>(Arrays.asList(sorts[0], sorts[5]))); 
                } 

【问题讨论】:

  • 排序的类型是什么?
  • 这是您今天提出的第二个此类问题。你能分享你的完整尝试吗?请创建一个minimal reproducible example
  • @hd1 它是一个字符串。
  • @Turing85 我的全部尝试不一定会为问题添加更多细节,因为我只是在这条线上遇到了麻烦。
  • 我要解决的这个问题来自 usaco 网站。该问题所属的比赛已经结束,因此允许就该问题进行讨论。这是问题的链接:usaco.org/index.php?page=viewproblem2&cpid=965 在问题页面上指定输入。

标签: java linkedhashset


【解决方案1】:

您可以使用流。

填充您的 hashSet。


      Set<Set<String>> nestedSet = new LinkedHashSet<>();

      LinkedHashSet<String> set1 =
            new LinkedHashSet<>(Set.of("alpha", "beta", "gamma", "delta", "epsilon"));
      LinkedHashSet<String> set2 =
            new LinkedHashSet<>(Set.of("apples", "oranges", "pears", "grapes", "bananas"));

      nestedSet.add(set2);
      nestedSet.add(set1);

测试数据

      Map<String, Boolean> testData = Map.of("alpha", true, "pears", true, 
      "papayas", false, "eta", false, "omega", false, "house", false);

运行它

      testData.forEach((item, expectedResult)-> {
         System.out.printf("Item = \"%s\", Expected return = %b, actual = %b%n",
               item,expectedResult, exists(nestedSet, item));
      });          

  public static boolean exists(Set<Set<String>> sets,
         String target) {
      return sets.stream().anyMatch(set->set.contains(target));
  }

【讨论】:

    【解决方案2】:

    您可以使用parallelSteam 使进程并发且快速-

    block.parallelStream()
         .filter(stringSet -> 
              stringSet.contains(input))
         .collect(Collectors.toList()).size() >  0
    

    上面的代码采用block (LinkedHashSet&lt;LinkedHashSet&lt;String&gt;&gt;) 和input 字符串。使用来自 fork join pool 的多个 thread 来查找不同集合中的输入字符串。最后它收集所有这样的集合其中包含输入字符串并检查大小是否大于0,如果是则返回true,否则返回false。

    编辑 1

    better version是这个-

    block.parallelStream().anyMatch(strings -> strings.contains(input))
    

    这样效率更高,因为它只会等待第一次匹配并立即返回true。

    anyMatchjavadoc -

     * Returns whether any elements of this stream match the provided
     * predicate.  May not evaluate the predicate on all elements if not
     * necessary for determining the result.  If the stream is empty then
     * {@code false} is returned and the predicate is not evaluated.
    

    【讨论】:

    • 你可能想做一些测试。 parallelStream 选项非常慢,除非有足够的数据来保证它的使用。设置线程等会有初始惩罚。
    • ForkJoinPool 公共池在 ForkJoinPool 类加载时被静态实例化。所以线程创建的惩罚是一次,这是任何线程创建都无法避免的。在大多数应用程序中恰好是正常用例之后,它将被重用。是的,你是对的,它是并行性的一般性问题,如果没有太多的处理时间,你可能会花费更多的时间。
    • @WJS 我看到了你的测试代码。您可以尝试多次运行一次执行中使用并行流,您应该会看到在以后的运行中获得更好的性能
    猜你喜欢
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2010-12-20
    • 2021-12-05
    • 2019-08-15
    相关资源
    最近更新 更多