在 Java 7 和 8 中创建与现有列表不同的列表?

2024-04-18

如果我有:

List<Integer> listInts = { 1, 1, 3, 77, 2, 19, 77, 123, 14, 123... }

在Java中创建一个有效的方法是什么List<Integer> listDistinctInts仅包含distinct值来自listInts?

我的直接想法是创建一个Set<Integer> setInts包含来自的所有值listInts然后打电话List<Integer> listDistinctInts = new ArrayList<>(setInts);

但这似乎可能效率低下 - 使用 Java 7 是否有更好的解决方案?

我没有使用 Java 8,但我相信使用它我可以做这样的事情(?):

List<Integer> listDistinctInts = listInts.stream().distinct().collect(Collectors.toList());

这会比上面的方法更高效和/或者在 Java 8 中是否有更有效的方法来做到这一点?

最后,(我知道提出多个问题可能会让人皱眉,但这是直接相关的)如果我只关心count中的不同元素listInts有没有更有效的方法来获取该值(在 Java 7 和 8 中) - 无需首先创建所有不同元素的列表或集合?

我对实现这一点的原生 Java 方法最感兴趣,并避免重新发明任何轮子,但如果手工代码或库提供更好的清晰度或性能,我会考虑它们。我读过这个相关问题Java - 不同的对象列表 https://stackoverflow.com/q/1019854/3651800但尚不完全清楚 Java 7 和 8 方法之间的性能差异,或者是否有更好的技术?


我现在已经从提供的优秀答案中对大多数建议选项进行了 MicroBenchmark。像大多数与性能相关的重要问题一样,哪个最好的答案是“这取决于”.

我所有的测试都是用JMHJava 微基准测试工具 http://openjdk.java.net/projects/code-tools/jmh/.

大多数测试都是使用 JDK 1.8 执行的,尽管我也使用 JDK 1.7 执行了一些测试,只是为了确保其性能不会有太大差异(几乎相同)。我测试了从迄今为止提供的答案中获取的以下技术:


1.Java 8 流- 解决方案使用stream()我曾提出使用 Java 8 的可能性:

public List<Integer> testJava8Stream(List<Integer> listInts) {
    return listInts.stream().distinct().collect(Collectors.toList());
}

pros 现代 Java 8 方法,无第三方依赖

cons 需要 Java 8


2. 添加到列表- 提出的解决方案维克多2748 https://stackoverflow.com/a/27464820/3651800当且仅当列表尚未包含该值时,才会构造并添加新列表。请注意,我还按照原始大小(最大可能)预分配目标列表,以防止任何重新分配:

public List<Integer> testAddingToList(List<Integer> listInts) {
    List<Integer> listDistinctInts = new ArrayList<>(listInts.size());
    for(Integer i : listInts)
    {
        if( !listDistinctInts.contains(i) ) { listDistinctInts.add(i); }
    }
    return listDistinctInts;
}

pros 适用于任何 Java 版本,无需创建 Set 然后复制,无需第 3 方依赖

cons 在构建列表时需要重复检查列表中的现有值


3. GS 快速收藏 (现在是 Eclipse 集合)- 提出的解决方案克雷格·莫特林 https://stackoverflow.com/a/27489572/3651800使用GS 馆藏库 https://github.com/goldmansachs/gs-collections以及他们的自定义列表类型FastList:

public List<Integer> testGsCollectionsFast(FastList listFast)
{
    return listFast.distinct();
}

pros 据报道,代码非常快速、简单且富有表现力,适用于 Java 7 和 8

cons 需要第 3 方库和FastList而不是常规的List<Integer>


4. GS系列改编- FastList 解决方案并不能完全进行同类比较,因为它需要一个FastList传递给方法而不是好的 ol'ArrayList<Integer>所以我也测试了Craig提出的适配器方法:

public List<Integer> testGsCollectionsAdapted(List<Integer> listInts)
{
    return listAdapter.adapt(listInts).distinct();
}

pros 不需要FastList,适用于 Java 7 和 8

cons 必须适应列表,因此可能性能不佳,需要第 3 方库


5.番石榴不可变集- 提出的方法路易斯·沃瑟曼 https://stackoverflow.com/a/12248480/3651800在评论中,以及卢声远盛源路 https://stackoverflow.com/a/27477005/3651800在他们的回答中使用Guava https://code.google.com/p/guava-libraries/:

public List<Integer> testGuavaImmutable(List<Integer> listInts)
{
    return ImmutableSet.copyOf(listInts).asList();
}

pros 据称速度非常快,适用于 Java 7 或 8

cons 返回一个Immutable List,无法处理输入列表中的空值,并且需要第 3 方库


7. 哈希集- 我最初的想法(也由EverV0id https://stackoverflow.com/a/27464848/3651800, ulix https://stackoverflow.com/a/27465914/3651800和无线电定义)

public List<Integer> testHashSet(List<Integer> listInts)
{
    return new ArrayList<Integer>(new HashSet<Integer>(listInts));
}

pros 适用于 Java 7 和 8,无第 3 方依赖项

cons 不保留列表的原始顺序,必须构造集合然后复制到列表。


6.LinkedHashSet- 自从HashSet解决方案没有保留原始列表中整数的顺序我还测试了一个使用 LinkedHashSet 来保留顺序的版本:

public List<Integer> testLinkedHashSet(List<Integer> listInts)
{
    return new ArrayList<Integer>(new LinkedHashSet<Integer>(listInts));
}

pros 保留原始顺序,适用于 Java 7 和 8,无第 3 方依赖项

cons 不太可能像平常一样快HashSet方法


Results

这是我对各种不同尺寸的结果listInts(结果从最慢到最快排序):

1. 与 ArrayList 不同,取 0-50,000 之间的 100,000 个随机整数(即大列表,一些重复)

Benchmark                Mode       Samples     Mean   Mean error    Units

AddingToList            thrpt        10        0.505        0.012    ops/s
Java8Stream             thrpt        10      234.932       31.959    ops/s
LinkedHashSet           thrpt        10      262.185       16.679    ops/s
HashSet                 thrpt        10      264.295       24.154    ops/s
GsCollectionsAdapted    thrpt        10      357.998       18.468    ops/s
GsCollectionsFast       thrpt        10      363.443       40.089    ops/s
GuavaImmutable          thrpt        10      469.423       26.056    ops/s

2. 取不同于 ArrayList 的 1000 个 0-50 之间的随机整数(即中等列表,许多重复项)

Benchmark                Mode       Samples     Mean   Mean error    Units

AddingToList            thrpt        10    32794.698     1154.113    ops/s
HashSet                 thrpt        10    61622.073     2752.557    ops/s
LinkedHashSet           thrpt        10    67155.865     1690.119    ops/s
Java8Stream             thrpt        10    87440.902    13517.925    ops/s
GsCollectionsFast       thrpt        10   103490.738    35302.201    ops/s
GsCollectionsAdapted    thrpt        10   143135.973     4733.601    ops/s
GuavaImmutable          thrpt        10   186301.330    13421.850    ops/s

3. 取不同于 ArrayList 的 100 个 0-100 之间的随机整数(即小列表,一些重复)

Benchmark                Mode       Samples     Mean   Mean error    Units

AddingToList            thrpt        10   278435.085    14229.285    ops/s
Java8Stream             thrpt        10   397664.052    24282.858    ops/s
LinkedHashSet           thrpt        10   462701.618    20098.435    ops/s
GsCollectionsAdapted    thrpt        10   477097.125    15212.580    ops/s
GsCollectionsFast       thrpt        10   511248.923    48155.211    ops/s
HashSet                 thrpt        10   512003.713    25886.696    ops/s
GuavaImmutable          thrpt        10  1082006.560    18716.012    ops/s

4. 取不同于 ArrayList 的 10 个 0-50 之间的随机整数(即小列表,很少重复)

Benchmark                Mode       Samples     Mean   Mean error    Units

Java8Stream             thrpt        10  2739774.758   306124.297    ops/s
LinkedHashSet           thrpt        10  3607479.332   150331.918    ops/s
HashSet                 thrpt        10  4238393.657   185624.358    ops/s
GsCollectionsAdapted    thrpt        10  5919254.755   495444.800    ops/s
GsCollectionsFast       thrpt        10  7916079.963  1708778.450    ops/s
AddingToList            thrpt        10  7931479.667   966331.036    ops/s
GuavaImmutable          thrpt        10  9021621.880   845936.861    ops/s

结论

  • 如果您只从列表中取出一次不同的项目,并且列表不是很长any这些方法应该足够了。

  • 最有效的通用方法来自第三方库:GS Collections 和 Guava 表现出色。

  • 在选择性能最佳的方法时,您可能需要考虑列表的大小以及可能的重复项数量。

  • 仅当值尚未存在时才添加到新列表的幼稚方法对于小型列表非常有效,但是一旦输入列表中包含多个值,它就会执行所尝试的方法中最差的方法。

  • 番石榴ImmutableSet.copyOf(listInts).asList()方法在大多数情况下效果最快。但请注意限制:返回的列表是Immutable并且输入列表不能包含空值。

  • The HashSet方法执行最好的非第 3 方方法,通常比 Java 8 流更好,但会重新排序整数(这可能是也可能不是问题,具体取决于您的用例)。

  • The LinkedHashSet方法保持顺序,但不出所料通常比 HashSet 方法更糟糕。

  • 这俩HashSet and LinkedHashSet当使用具有复杂 HashCode 计算的数据类型列表时,方法的性能会更差,因此,如果您尝试选择不同的数据类型,请自行进行分析Foos 来自 aList<Foo>.

  • 如果你已经有GS系列 https://github.com/goldmansachs/gs-collections作为依赖项,它的性能非常好,并且比 ImmutableList 更灵活Guava https://code.google.com/p/guava-libraries/方法。如果您没有将其作为依赖项,并且选择不同项目的性能对于应用程序的性能至关重要,则值得考虑添加它。

  • 令人失望的是,Java 8 流的性能似乎相当差。可能有更好的编码方式distinct()调用方式比我使用的方式更好,所以当然欢迎评论或其他答案。

注意。我不是微基准测试专家,因此如果有人发现我的结果或方法存在缺陷,请通知我,我将尽力纠正答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Java 7 和 8 中创建与现有列表不同的列表? 的相关文章

随机推荐

  • Android Twilio 视频通话,唤醒应用程序并带到前台

    我正在尝试使用 Twilio Video Call 提供本机视频通话体验 这是场景 人 AAA 称人 BBB BBB 没有打开应用程序 在后台或前台 应用程序处于终止状态 手机甚至可能被锁定 当来自 AAA 的电话到达时 应用程序将打开 并
  • 投影 - 将 3d 转换为 2d

    我有问题或者很好 我不知道如何将具有 x y z 值的 3d 点转换为 2d 点 我必须绘制投影 其中我确实有点的 x y z 值 但我不知道如何将它们转换为 2d 以便我可以将它们移动到我的轴上 我一直在浏览维基和谷歌 但是我不太确定应该
  • Networkx中的多层图

    我想创建一个多层图 如附图所示 通过连接用以下代码编写的两个图 使用networkx Graph g1 nx read edgelist sample txt nodetype str pos nx shell layout g plt f
  • 春季启动。如何禁用 JPA 有条件初始化

    如果可以完全禁用 JPA Stack 的初始化 我会很伤心 在某些情况下 我的应用程序是在无法访问数据库的环境中执行的 应用程序可以在应用程序级别上幸存下来 但从技术上讲 我在数据源的初始化方面遇到了一些异常 必须有某种方法来完全禁用 JP
  • scala 中的reduceLeft(或foldLeft)与reduceRight(或foldRight)

    我正在从 coursera 学习 scala 在里面reduceLeft and reduceRight描述如下 然后在下一张幻灯片上 老师说这个代码模式被抽象为reduceLeft 我的问题 我认为第一张幻灯片中的模式是reduceRig
  • 寻找包含当前节点的 jQuery find(..) 方法

    jQueryfind http api jquery com find 遍历方法不包括当前节点 它从当前节点的子节点开始 调用将当前节点包含在其匹配算法中的查找操作的最佳方法是什么 浏览文档并没有立即引起我的注意 对于 jQuery 1 8
  • Symfony2 php.ini

    当检查时app check php Symfony2说这个Configuration file used by PHP etc php5 cli php ini然而phpinfo 显示 Apache 正在使用 etc php5 apache
  • 如何让两个模型互相引用 Django

    我有以下代码 class Game models Model title models CharField max length 50 summery models CharField max length 500 key models I
  • Laravel 5 将数据从中间件传递到控制器

    我的中间件类似于Auth 它检查 URL 模式 例如 rest 然后在请求中查找令牌 从数据库中检索其相应的用户 之后 我想将该用户保存在一个变量中 以便稍后可以在以下任何控制器中返回该用户 最好的办法是什么 中间件 public func
  • LINQ 删除重复项和结果项以获得数量总和

    我只是想检查是否有更快的方法使用 LINQ 通过 id 从重复项中删除列表 但在结果列表项中将具有一些其他属性的总和 在本例中为价格 例如 起始列表 List
  • 通过 Open Graph API 以编程方式创建 Facebook 页面

    我希望有一种方法可以使用开放图 API 创建 Facebook 页面 该文档仅显示页面存在后我可以进行的 API 调用 目前 我的网站上有电影简介 我想在 Facebook 上为每个电影简介创建一个页面 我知道我可以添加 赞 按钮 一旦单击
  • @Transactional 和 AOP 之间的混淆

    Transactional 是否在 Spring 3 中替代了 AOP 它们相同吗 我可以说 Transactional在内部实现了AOP吗 The Transactionnal注释只是声明方法 或类的所有方法 是事务性的简单方法 Spri
  • 检测 MATLAB 帮助浏览器

    我想为大型 MATLAB 应用程序创建一些 HTML 文档 主要在 MATLAB 帮助浏览器 从 11b 开始的任何版本的 MATLAB 中 查看 这将有一些自定义 CSS 但没有什么非常复杂的 但是 我还希望在其他浏览器中可以查看相同的文
  • 如何创建一个 numpy 数组来描述三角形的顶点?

    我喜欢使用 Numpy 创建要传递到的顶点数组glsl Vertices将是一个包含 3 个顶点信息的 numpy 数组 Each vertex包括 pos x y 具有 32 位的 64 位有符号浮点格式 R 分量位于字节 0 3 中 3
  • 如何查看SQL Server 2008中表空间的总使用量?

    在 SQL server 2008 中 我如何 通过 SQL 查询 找到 SQL Server 2008 R2 的特定实例 或所有实例 的表空间使用百分比 另外 获取 SQL Server 的所有命名实例的列表的最佳方法 查询 是什么 这是
  • 如何在我的开发环境中管理多个版本的 Scala 和 SBT?

    我刚刚完成了很棒的 Coursera Scala 课程 并渴望通过探索一些现有的开源项目来继续了解有关 Scala 的更多信息 不过 我在尝试让其中一些在本地运行时遇到了障碍 我有 Ruby 背景 我们使用诸如rvm or rbenv在一个
  • Android 形状背景

    是否可以在 xml 中绘制一个形状 并使用 png 作为该形状的背景 我已经有了形状 它是一个带圆角的正方形 我想为该正方形添加背景 是的 您可以使用任何形状文件作为任何视图的背景 此示例创建圆形背景 形状周围有白色和黑色边框 样本 圆角
  • 护照验证不重定向

    我正在编写一个本地注册策略 发现它不起作用 所以我退后一步 尝试对我的空集合进行身份验证 每次我提交表单都会花费大约 30 40 秒的时间 直到导致超时 我确保调用了 Passport authenticate 但似乎它没有执行任何重定向
  • 在 Android 中初始化 Firebase crashlytics

    我已在我的 Android 项目中将 Fabric Crashlytics 迁移到 Firebase Crashlytics 在使用织物时 在活动课上我使用了以下线 Fabric with this new Crashlytics 但迁移后
  • 在 Java 7 和 8 中创建与现有列表不同的列表?

    如果我有 List