Java 8在一个对象列表中查找具有另一个对象的匹配元素。

huangapple go评论72阅读模式
英文:

Java 8 find element matching in a list of objects where each object has another object

问题

I have two classes:

class SampleClass {
private String testString;
private List


class Label {
private String labelName;
private String labelValue;
}


I have a `List<SampleClass> sampleClassList`. I need to find the find element in the list which has a particular `labelName` and `labelValue` using Java 8.

If I need to get the `SampleClass` object based on `testString` I would do,

Optional sampleClass = sampleClassList.stream().filter(entry -> entry.getTestString().equals("some_value")).findFirst();


Now that the filtering involves `Label` class, I am unable to figure out how to do that. I have tried something like,

Optional sampleClass = sampleClassList.stream().filter(entry ->
entry.getLabels().stream().anyMatch(label ->
label.getLabelName().equals("some_name") &&
label.getLabelValue().equals("some_value"))).findFirst();


for which I get `Bad return type in lambda expression: Optional<Label> cannot be converted to boolean`. How would I go about making this change?

I could make it work by using `contains()` method

final Optional sampleClass = sampleClassList.stream()
.filter(entry -> entry.getLabels()
.contains(new Label().withLabelName("some_name").withLabelValue("some_value")))
.findFirst();


but would like to know if I can still use `stream()` to make this happen.
英文:

I have two classes:

class SampleClass {
   private String testString;
   private List&lt;Label&gt; labels; 
}
class Label {
   private String labelName;
   private String labelValue;
}

I have a List&lt;SampleClass&gt; sampleClassList. I need to find the find element in the list which has a particular labelName and labelValue using Java 8.

If I need to get the SampleClass object based on testString I would do,

Optional&lt;SampleClass&gt; sampleClass = sampleClassList.stream().filter(entry -&gt; entry.getTestString().equals(&quot;some_value&quot;).findFirst();

Now that the filtering involves Label class, I am unable to figure out how to do that. I have tried something like,

Optional&lt;SampleClass&gt; sampleClass = sampleClassList.stream().filter(entry -&gt; 
                                       entry.getLabels().stream().filter(label -&gt; 
                                            label.getName().equals(&quot;some_name&quot;) &amp;&amp; 
                                            label.getValue().equals(&quot;some_value&quot;)).findFirst()).findFirst();

for which I get Bad return type in lambda expression: Optional&lt;Label&gt; cannot be converted to boolean. How would I go about making this change?

I could make it work by using contains() method

final Optional&lt;SampleClass&gt; sampleClass = sampleClassList.stream()
                    .filter(entry -&gt; entry.getLabels()
                            .contains(new Label().withLabelName(&quot;some_name&quot;).withLabelValue(&quot;some_value&quot;)))
                    .findFirst();

but would like to know if I can still use stream() to make this happen.

答案1

得分: 1

如何看待这个问题不使用建议的 `findFirst().isPresent()`,你可以直接使用 `anyMatch()`

public class Label {
  private String name;
  private String value;

  public Label(String name, String value) {
    this.name = name;
    this.value = value;
  }

  public String getName() {
    return name;
  }

  public String getValue() {
    return value;
  }

  @Override
  public String toString() {
    return "Label{" + "name='" + name + '\'' + ", value='" + value + '\'' + '}';
  }
}

class SampleClass {
  private String testString;
  private List<Label> labels;

  public SampleClass(String testString, List<Label> labels) {
    this.testString = testString;
    this.labels = labels;
  }

  public List<Label> getLabels() {
    return labels;
  }

  @Override
  public String toString() {
    return "SampleClass{" + "testString='" + testString + '\'' + ", labels=" + labels + '}';
  }
}

import java.util.List;
import java.util.Optional;

class Scratch {
  public static void main(String[] args) {
    List<SampleClass> sampleClassList = List.of(
      new SampleClass("111", List.of(new Label("one", "one value"), new Label("two", "two value"))),
      new SampleClass("222", List.of(new Label("one", "one value"), new Label("two", "two value"))),
      new SampleClass("333", List.of(new Label("some_name", "some_value"), new Label("two", "two value")))
    );
    Optional<SampleClass> sampleClass = sampleClassList.stream()
      .filter(entry ->
        entry.getLabels().stream()
          .anyMatch(label ->
            label.getName().equals("some_name") &&
              label.getValue().equals("some_value")
          )
      )
      .findFirst();
    System.out.println(sampleClass.orElse(null));
  }
}

这将打印出

SampleClass{testString='333', labels=[Label{name='some_name', value='some_value'}, Label{name='two', value='two value'}]}
英文:

How about this? Instead of the suggested findFirst().isPresent() you can just use anyMatch()

public class Label {
  private String name;
  private String value;

  public Label(String name, String value) {
    this.name = name;
    this.value = value;
  }

  public String getName() {
    return name;
  }

  public String getValue() {
    return value;
  }

  @Override
  public String toString() {
    return &quot;Label{&quot; + &quot;name=&#39;&quot; + name + &#39;\&#39;&#39; + &quot;, value=&#39;&quot; + value + &#39;\&#39;&#39; + &#39;}&#39;;
    }
}
class SampleClass {
  private String testString;
  private List&lt;Label&gt; labels;

  public SampleClass(String testString, List&lt;Label&gt; labels) {
    this.testString = testString;
    this.labels = labels;
  }

  public List&lt;Label&gt; getLabels() {
    return labels;
  }

  @Override
  public String toString() {
    return &quot;SampleClass{&quot; + &quot;testString=&#39;&quot; + testString + &#39;\&#39;&#39; + &quot;, labels=&quot; + labels + &#39;}&#39;;
  }
}
import java.util.List;
import java.util.Optional;

class Scratch {
  public static void main(String[] args) {
    List&lt;SampleClass&gt; sampleClassList = List.of(
      new SampleClass(&quot;111&quot;, List.of(new Label(&quot;one&quot;, &quot;one value&quot;), new Label(&quot;two&quot;, &quot;two value&quot;))),
      new SampleClass(&quot;222&quot;, List.of(new Label(&quot;one&quot;, &quot;one value&quot;), new Label(&quot;two&quot;, &quot;two value&quot;))),
      new SampleClass(&quot;333&quot;, List.of(new Label(&quot;some_name&quot;, &quot;some_value&quot;), new Label(&quot;two&quot;, &quot;two value&quot;)))
    );
    Optional&lt;SampleClass&gt; sampleClass = sampleClassList.stream()
      .filter(entry -&gt;
        entry.getLabels().stream()
          .anyMatch(label -&gt;
            label.getName().equals(&quot;some_name&quot;) &amp;&amp;
              label.getValue().equals(&quot;some_value&quot;)
          )
      )
      .findFirst();
    System.out.println(sampleClass.orElse(null));
  }
}

This should print:

SampleClass{testString=&#39;333&#39;, labels=[Label{name=&#39;some_name&#39;, value=&#39;some_value&#39;}, Label{name=&#39;two&#39;, value=&#39;two value&#39;}]}

答案2

得分: 0

你之所以收到该错误信息,是因为

label -> label.getName().equals("some_name") && label.getValue().equals("some_value")).findFirst()

返回一个Optional

英文:

You're getting that error message because

label -&gt; label.getName().equals(&quot;some_name&quot;) &amp;&amp; label.getValue().equals(&quot;some_value&quot;)).findFirst()

returns an Optional<Label> when Java needs a boolean for your outer filter. Essentially you're saying give me an Optional that contains the value if it exists. If you change the findFirst() to isPresent() then that will give you the boolean you need as isPresent() just says return true if the value exists.

答案3

得分: 0

sampleClassList.stream().filter(entry ->
                entry.getLabels().stream().filter(label ->
                        label.getName().equals("some_name") &&
                                label.getValue().equals("some_value")).count() > 0).findFirst();

在过滤内部标签列表后使用 count() > 0。

英文:
sampleClassList.stream().filter(entry -&gt;
entry.getLabels().stream().filter(label -&gt;
label.getName().equals(&quot;some_name&quot;) &amp;&amp;
label.getValue().equals(&quot;some_value&quot;)).count() &gt; 0).findFirst();

use count() > 0 after filtering on inner labels List

huangapple
  • 本文由 发表于 2020年10月11日 08:24:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/64299543.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定