使用Java Streams从超集中获取子集

时间:2018-05-22 08:33:33

标签: java list arraylist java-8 java-stream

我需要从给定的超级列表中获取子列表,如下所述。

假设我有一个“人物”对象的超级列表,如下所示:

List<Person> personsList = new ArrayList<>();
personsList.add(new Person("John", 28));
personsList.add(new Person("Paul", 29));
personsList.add(new Person("Adam", 30));
personsList.add(new Person("Peter", 31));
personsList.add(new Person("Pat", 32));

让Person类定义如下:

class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + ": " + age;
    }
}

给出这样的子列表:

String [] names = {"John", "Paul", "Adam"};
List<String> namesList = Arrays.asList(names);

我想获取姓名为JohnPaulAdam的人物对象。

我是Java流的新手,这是我到目前为止所做的尝试,以满足我的要求。

List<Person> finalList = personsList.stream().filter(p -> namesList.contains(p.name))
                .collect(Collectors.toCollection(() -> new ArrayList<Person>()));

我得到了理想的结果,但我想知道是否还有其他有效的方法来实现这一点(我主要看一下namesList.contains(p.name)的效率有点低。)

如果有更好的方法,请告诉我。

2 个答案:

答案 0 :(得分:4)

假设在数组中有重复的名称是没有意义的,最好的方法是在Set<T>名称中找到名称。这很容易实现。将数组转换为List,并在接受任何集合后立即将其包含在HashSet<T>的构造函数中。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button type="button" class="js-add-category">Add Category</button><br><br>
<div class="main-content" data-count="1">

  <div class="typical serv-content">
    <div class="serv-content">
      <div class="title-content">
        <input type="text" id="name-title-#cat#" class="name-title" value="name-#cat#">
      </div>
      <div class="action-btn">
        <button type="button" class="js-add-section">Add Section</button>
        <button type="button" class="js-save-section">Save</button>
      </div>
    </div>
  </div>

  <div class="typical cars-item">
    <div class="cars-item js-cars-item" data-count="1">
      <ul>
        <li>
          <input type="checkbox" id="car-#cat#-#sec#-1">
          <label for="car-#cat#-#sec#-1"><i class="icon-tick"></i></label>
        </li>
        <li>
          <input type="checkbox" id="car-#cat#-#sec#-2">
          <label for="car-#cat#-#sec#-2"><i class="icon-tick"></i></label>
        </li>
        <li>
          <input type="checkbox" id="car-#cat#-#sec#-3">
          <label for="car-#cat#-#sec#-3"><i class="icon-tick"></i></label>
        </li>
      </ul>

      <div class="footer">
        <span class="num"> Section #sec# </span>
      </div>
    </div>
  </div>

</div>

现在使用Stream-API与您尝试的相同。仅使用静态方法Collectors.toList()

String [] names = {"John", "Paul", "Adam"};
Set<String> set = new HashSet<>(Arrays.asList(names));

结果将仅包含List<Person> list= personsList.stream() .filter(i -> set.contains(i.getName())) .collect(Collectors.toList()); JohnPaul个人&#39;对象。

答案 1 :(得分:2)

nameList定义为Set会更有效,但如果列表中只包含3个名称,则差异不会明显。

这样的事情:

Set<String> namesList = new HashSet<> (Arrays.asList("John", "Paul", "Adam"));

List<Person> finalList = personsList.stream()
                                    .filter(p -> namesList.contains(p.name))
                                    .collect(Collectors.toList());

注意:我还将收藏家更改为toList,因为这是您显然需要的。