java 流图过滤器效率

yxyvkwin  于 2022-12-17  发布在  Java
关注(0)|答案(4)|浏览(128)

想想这门课-

Class Person {
    private Integer age;
    private Integer getAge() {
        return this.age;
    }
}

List<Person> list = new ArrayList<Person>..大约20个示例
现在我必须找到所有的成年人(年龄〉= 18)我有两种方法来做它与流-
1.

list.stream()
    .map(person -> person.getAge())
    .filter(age -> age >= 18)
    .count()


1.

list.stream()
    .filter(person -> person.getAge() >= 18)
    .count()

现在我的问题是:方法1会增加额外的迭代来执行任务,还是像方法2一样只进行一次迭代?

zynd9foi

zynd9foi1#

一个流只能被消耗一次,所以没有“额外的迭代”。有一个额外的步骤,所以从技术上讲,第二个更有效。然而,你必须有数百万个元素,即使这样,它也几乎不明显。
在这种情况下,它主要是一个选择,在哪种风格你更喜欢。因为他们都很容易阅读,第二个更有意义,因为它更简单。

aor9mmx1

aor9mmx12#

Stream.filter和Stream.map是返回新流的中间操作。但是这些中间操作总是***懒惰的***:https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps
懒惰地处理流允许显著的效率;在诸如上述滤波器-Map-求和示例的流水线中,滤波、Map和求和可被融合到对数据的单次通过中,具有最小的中间状态。

c9qzyr3d

c9qzyr3d3#

使用Java流操作有时候可能有点棘手。

我将向您展示一个用Kotlin编写的示例,并显示反编译版本
想象一个namevalue的类成员
通过这些代码,我想按年龄的值过滤姓名

功能A:使用过滤器和Map

fun a(list: List<Person>): List<String> {
    return list
        .filter { it.age >= 18 }
        .map { it.name }
}

功能B:使用简单的Foreach

fun b(list: List<Person>): List<String> {
    val result = mutableListOf<String>()
    for (item in list) {
        if (item.age >= 18) {
            result.add(item.name)
        }
    }
    return result
}

A功能是多么美丽!!

现在,让我们看看引擎盖下发生了什么:

事实上,函数A使用Two While迭代器来执行相同的操作

我知道这有点乱

功能A:使用过滤器和Map

public final List a(@NotNull List list) {
  Intrinsics.checkNotNullParameter(list, "list");
  Iterable $this$map$iv = (Iterable)list;
  int $i$f$map = false;
  Collection destination$iv$iv = (Collection)(new ArrayList());
  int $i$f$mapTo = false;
  Iterator var7 = $this$map$iv.iterator();

  Object item$iv$iv;
  Person it;
  boolean var10;
  while(var7.hasNext()) {
     item$iv$iv = var7.next();
     it = (Person)item$iv$iv;
     var10 = false;
     if (it.getAge() >= 18) {
        destination$iv$iv.add(item$iv$iv);
     }
  }

  $this$map$iv = (Iterable)((List)destination$iv$iv);
  $i$f$map = false;
  destination$iv$iv = (Collection)(new ArrayList(CollectionsKt.collectionSizeOrDefault($this$map$iv, 10)));
  $i$f$mapTo = false;
  var7 = $this$map$iv.iterator();

  while(var7.hasNext()) {
     item$iv$iv = var7.next();
     it = (Person)item$iv$iv;
     var10 = false;
     String var12 = it.getName();
     destination$iv$iv.add(var12);
  }

  return (List)destination$iv$iv;

}

功能B:使用简单的Foreach

public final List b(@NotNull List list) {
  Intrinsics.checkNotNullParameter(list, "list");
  List result = (List)(new ArrayList());
  Iterator var4 = list.iterator();

  while(var4.hasNext()) {
     Person item = (Person)var4.next();
     if (item.getAge() >= 18) {
        String var10001 = item.getName();
        Intrinsics.checkNotNullExpressionValue(var10001, "item.name");
        result.add(var10001);
     }
  }

  return result;

}

z18hc3ub

z18hc3ub4#

实际上第二种方法更好,因为每个stream方法都会产生一个新的流。例如,map方法返回一个new流,这里有一个文档,所以从计算次数的Angular 来看,第二种方法更便宜
顺便说一句,在第二个示例中,看起来您做了一个错误的sprint:不是list.filter而是list.stream().filter

相关问题