与有条件的流有关hashmap的迭代

发布于 2025-02-11 19:40:46 字数 363 浏览 1 评论 0原文

因此,我现在有这个循环

for (Map.Entry<String, Integer> val : map.entrySet()) {
        if (val.getValue() >= 10 && !Objects.equals(val.getKey(), " ") && val.getKey().length() > 3) {
            stats = stats + val.getKey().toLowerCase() + " - " + val.getValue() + "\n";
        }
    }

,我想摆脱循环和使用流的条件。我该怎么做?

So I have this loop

for (Map.Entry<String, Integer> val : map.entrySet()) {
        if (val.getValue() >= 10 && !Objects.equals(val.getKey(), " ") && val.getKey().length() > 3) {
            stats = stats + val.getKey().toLowerCase() + " - " + val.getValue() + "\n";
        }
    }

Now I want to get rid of for loop and if condition using streams. How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

救赎№ 2025-02-18 19:40:46

这可能是一种方法:

String stats = map.entrySet().stream()
        // keep only the entries you're interested in:
        .filter(entry -> entry.getKey().length() > 3 && entry.getValue() >= 10)
        // serialise entries one by one:
        .map(entry -> entry.getKey().toLowerCase() + " - " + entry.getValue())
        // join:
        .collect(Collectors.joining("\n"));

Here could be an approach:

String stats = map.entrySet().stream()
        // keep only the entries you're interested in:
        .filter(entry -> entry.getKey().length() > 3 && entry.getValue() >= 10)
        // serialise entries one by one:
        .map(entry -> entry.getKey().toLowerCase() + " - " + entry.getValue())
        // join:
        .collect(Collectors.joining("\n"));
送君千里 2025-02-18 19:40:46

有很多方法,这是一种。

  • 首先一些测试数据。
Map<String, Integer> map = Map.of(" ", 18, "foo", 14, "abcd",
        20, "ab", 10, "efgh", 3, "rstuv", 14);
  • 然后,我将定义A 谓词&lt; string&lt; string,Integer&gt;&gt;以减少流构造的杂物。请注意,由于您正在检查长度&lt; 3可以省略单个空间的条件。如果您是要检查空白字符串,则可以使用!val.getKey()。isblank()作为条件。

  • 降低采用初始参数,然后是binaryoperator作为累加器。在这种情况下,积累是映射字符串的串联。 String :: Concat符合要求,并在此处用于完成操作。

Predicate<Entry<String, Integer>> check =
        val -> val.getValue() >= 10
                && val.getKey().length() > 3;

然后,这只是流式传输entryset的问题。

String result = map.entrySet().stream().filter(check)
         .map(e -> e.getKey().toLowerCase() + " - " + e.getValue() + "\n")
         .reduce("", String::concat);

Systemm.out.print(result);

打印以下内容。

abcd - 20
rstuv - 14

There are many approaches, here is one.

  • first some test data.
Map<String, Integer> map = Map.of(" ", 18, "foo", 14, "abcd",
        20, "ab", 10, "efgh", 3, "rstuv", 14);
  • Then I would define a Predicate<Entry<String, Integer>> to reduce the clutter of the stream construct. Note that since you are checking for length < 3 the condition for a single space can be omitted. If you meant check for a blank String, you can use !val.getKey().isBlank() as the condition.

  • reduce takes an initial argument followed by a BinaryOperator as an accumulator. In this case the accumulation is a concatenation of the mapped strings. String::concat meets the requirements and is used here to fulfill the operation.

Predicate<Entry<String, Integer>> check =
        val -> val.getValue() >= 10
                && val.getKey().length() > 3;

Then it is just a matter of streaming the EntrySet.

String result = map.entrySet().stream().filter(check)
         .map(e -> e.getKey().toLowerCase() + " - " + e.getValue() + "\n")
         .reduce("", String::concat);

Systemm.out.print(result);

Prints the following.

abcd - 20
rstuv - 14
懵少女 2025-02-18 19:40:46

要充分利用流功能,您需要使用流,过滤和减少功能如下:

// Get the stream from entrySet
String result = map.entrySet().stream()    
      // Filter entries based on your condition
      .filter(val ->  val.getValue() >= 10 
                           && !Objects.equals(val.getKey(), " ") 
                           && val.getKey().length() > 3)  
       // Apply the reduce to combine filtered entries in a single string     
      .reduce("", (stats, val) -> stats 
                                  + val.getKey().toLowerCase() 
                                  + " - " 
                                  + val.getValue() 
                                  + "\n");

将其作为其来源返回顺序流。

过滤器在流上应用的方法:

返回由与给定谓词相匹配的该流元素的流。

降低在流对象上功能:

使用提供的身份值和关联累积函数对该流的元素进行减少,并返回降低的值

To have a full use of stream functionalities You need to use stream, filter and reduce functions as follow:

// Get the stream from entrySet
String result = map.entrySet().stream()    
      // Filter entries based on your condition
      .filter(val ->  val.getValue() >= 10 
                           && !Objects.equals(val.getKey(), " ") 
                           && val.getKey().length() > 3)  
       // Apply the reduce to combine filtered entries in a single string     
      .reduce("", (stats, val) -> stats 
                                  + val.getKey().toLowerCase() 
                                  + " - " 
                                  + val.getValue() 
                                  + "\n");

The stream method applied to a Collection give a new Stream of the item present in the set:

Returns a sequential Stream with this collection as its source.

The filter method appplied on the stream:

Returns a stream consisting of the elements of this stream that match the given predicate.

The reduce function on the stream object:

Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value

£噩梦荏苒 2025-02-18 19:40:46

使用foreach方法的好工作。最好使用流和流API。

这是一个非常简单的程序,可以做类似于您想做的事情。

import java.util.Map;
import java.util.HashMap;
public class Test {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("aaaa", 1);
        map.put("bbbb", 2);
        map.put("cccc", 3);
        map.forEach((k,v)->System.out.println(k + ": " + v));
    }
}

现在,我们可以编译并运行代码。

% javac Test.java
% java Test
aaaa: 1
bbbb: 2
cccc: 3

现在,您的代码中有什么错误?

错误是这样。 MAP.FOREACH方法采用双调节器。双调查器操作采用两个输入参数(K和V),并且返回没有结果。您正在使用双调查器操作来返回三元表达式中的结果。双调节器操作具有返回类型的void类型。因此,您可以做的是...您可以执行双项量操作内部的代码(就像我在示例中一样),但是您无法返回双调解器操作中的结果(您正在尝试执行此操作)。

您可以在Java文档中阅读有关MAP.FORECH方法和Biconsumer功能操作的信息。

  1. 地图的java文档
  2. java docs for Biconsumer操作

Good job using the forEach method. It's good practice to use streams and the stream API.

Here's a very simple program that does something similar to what you want to do.

import java.util.Map;
import java.util.HashMap;
public class Test {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("aaaa", 1);
        map.put("bbbb", 2);
        map.put("cccc", 3);
        map.forEach((k,v)->System.out.println(k + ": " + v));
    }
}

Now we can compile and run the code.

% javac Test.java
% java Test
aaaa: 1
bbbb: 2
cccc: 3

Now, what's the error in your code?

The error is this. The Map.forEach method takes a BiConsumer. The BiConsumer operation takes two input arguments (k and v) and returns no result. You are using a BiConsumer operation to return a result in a ternary expression. The BiConsumer operation has a return type of void. So what you can do is... you can execute code inside of the BiConsumer operation (like I did in my example) but you cannot return a result in the BiConsumer operation (which you are trying to do).

You can read about the Map.forEach method and the BiConsumer functional operation in the Java docs.

  1. Java docs for the Map.forEach method
  2. Java docs for the BiConsumer operation
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文