占用内存的Enum.values()方法
我是Java 枚举的忠实拥护者 。 似乎我们一直在等待获得它,但是当我们最终获得它( J2SE 5 )时,该枚举比C和C ++提供的枚举要好得多,在我看来,这“ 值得等待” 。 与Java enum
一样好,它也不是没有问题。 特别是,Java枚举的方法values()
返回数组的新副本,该副本表示每次调用时可能的值。
Java语言规范阐明了枚举行为。 在Java语言规范Java SE 10 Edition中 , 第8.9节涵盖了枚举。 第8.9.3节 (“枚举成员”)列出了两个“隐式声明的方法”: public static E[] values()
和public static E valueOf(String name)
。 例8.9.3-1 (“使用增强的for
循环遍历枚举常量”)演示了如何调用Enum.values()
遍历枚举。 但是,问题在于Enum.values()
返回一个数组,而Java中的数组是可变的[Java语言规范的10.9节 (“字符数组不是字符串”)提醒我们,当在Java之间进行区分时) string
和Java字符数组。]。 Java枚举是紧密不变的,因此有意义的是,每次调用该枚举以确保不更改与该枚举关联的数组时,该枚举必须返回由values()
方法返回的数组的克隆。
OpenJDK 编译器-开发邮件列表上最近的一篇标题为“ 关于Enum.values()内存分配 ”的文章指出,在紧密循环中调用Enum.values()
会克隆常量值数组时,会分配大量内存。 ” 该消息的发布者补充说,这“可能是出于不变性”,并指出:“我能理解。” 该消息还引用了同一邮件列表上的2012年3月消息和相关主题。
编译器开发邮件列表上的两个线程包括一些有趣的当前可用的解决方法。
- 将
values()
返回的枚举值数组缓存为元素的private static final
数组,该元素的初始private static final
数组初始化为values()
返回的数组。 - 缓存枚举值的固定
List
。 - 创建一个枚举值的
EnumSet
。
Brian Goetz在该线程上的消息开头是“这本质上是API设计错误; 因为values()返回一个数组,并且数组是可变的,所以每次都必须复制该数组。” [Goetz在该消息中还嘲笑了“ 冻结数组 ”(使Java数组变得不可变)的概念。]
这个问题不是新问题。 威廉·希尔兹(William Shields)在2009年12月发布的文章《 Java中的可变性,数组和临时对象的成本 》指出:“所有这些的最大问题是Java数组是可变的。” Shields在写由Enum.values()
提出的特定问题之前,先解释了Java Date类中可变性的古老和众所周知的问题:
Java枚举有一个称为values()
的静态方法,该方法返回该enum
的所有实例的数组 。 在Date
类的课程中,这个特殊的决定令人震惊。 List
本来是更明智的选择。 在内部,这意味着实例数组每次调用时都必须进行防御性复制...
对此问题的其他引用包括“ Enums.values()方法 ”(Guava线程)和“ Java的Enum.values()隐藏分配 ”(显示缓存Enum.values()
返回的数组)。 上面还写了一个JDK错误: JDK-8073381 (“需要API来获取枚举值而不创建新数组”)。
下一篇代码清单中说明了本文中讨论的一些当前可用的变通方法,这是一个简单的Fruit
枚举,演示了以三种不同格式缓存该枚举的值。
具有三个“值”的缓存集的Fruit.java枚举
package dustin.examples.enums;import java.util.EnumSet;
import java.util.List;/*** Fruit enum that demonstrates some currently available* approaches for caching an enum's values so that a new* copy of those values does not need to be instantiated* each time .values() is called.*/
public enum Fruit
{APPLE("Apple"),APRICOT("Apricot"),BANANA("Banana"),BLACKBERRY("Blackberry"),BLUEBERRY("Blueberry"),BOYSENBERRY("Boysenberry"),CANTALOUPE("Cantaloupe"),CHERRY("Cherry"),CRANBERRY("Cranberry"),GRAPE("Grape"),GRAPEFRUIT("Grapefruit"),GUAVA("Guava"),HONEYDEW("Honeydew"),KIWI("Kiwi"),KUMQUAT("Kumquat"),LEMON("Lemon"),LIME("Lime"),MANGO("Mango"),ORANGE("Orange"),PAPAYA("Papaya"),PEACH("Peach"),PEAR("Pear"),PLUM("Plum"),RASPBERRY("Raspberry"),STRAWBERRY("Strawberry"),TANGERINE("Tangerine"),WATERMELON("Watermelon");private String fruitName;Fruit(final String newFruitName){fruitName = newFruitName;}/** Cached fruits in immutable list. */private static final List<Fruit> cachedFruitsList = List.of(Fruit.values());/** Cached fruits in EnumSet. */private static final EnumSet<Fruit> cachedFruitsEnumSet = EnumSet.allOf(Fruit.class);/** Cached fruits in original array form. */private static final Fruit[] cachedFruits = Fruit.values();public static List<Fruit> cachedListValues(){return cachedFruitsList;}public static EnumSet<Fruit> cachedEnumSetValues(){return cachedFruitsEnumSet;}public static Fruit[] cachedArrayValues(){return cachedFruits;}
}
在许多情况下,每次调用Enum.values()
必须克隆其数组的事实实际上并不重要。 也就是说,不难想象在“紧缩循环”中反复调用Enum.values()
会很有用,然后每次将枚举值复制到数组中都会对内存产生明显影响的情况并不难使用以及与更大内存使用相关的问题。 如果有一种标准的方法来以更有效的内存方式访问枚举的值,那就太好了。 前面提到的两个线程讨论了一些潜在实现此功能的想法。
翻译自: https://www.javacodegeeks.com/2018/08/memory-hogging-enum-values-method.html
占用内存的Enum.values()方法相关推荐
- enum.values_占用内存的Enum.values()方法
enum.values 我是Java 枚举的忠实拥护者 . 似乎我们一直在等待获得它,但是当我们最终获得它( J2SE 5 )时,该枚举比C和C ++提供的枚举要好得多,对我来说似乎" 值得 ...
- php phpqueey内存泄露,phpQuery 占用内存过多的处理方法
phpQuery 占用内存过多的处理方法 phpQuery 是一个用 php 实现的类似 jQuery 的开源项目, 可以在服务器端以 jQuery 的语法形式解析网页元素 相对于正则或其它方式匹配网 ...
- SQL Server 2008 R2占用内存越来越大解决方法
SQL Server 2008 R2占用内存越来越大解决方法 参考文章: (1)SQL Server 2008 R2占用内存越来越大解决方法 (2)https://www.cnblogs.com/pe ...
- C# Winform应用程序占用内存较大解决方法整理(转)
C# Winform应用程序占用内存较大解决方法整理(转) 参考文章: (1)C# Winform应用程序占用内存较大解决方法整理(转) (2)https://www.cnblogs.com/xcsn ...
- C# Winform应用程序占用内存较大解决方法整理(转)-- SetProcessWorkingSetSize
一.C# Winform应用程序占用内存较大解决方法整理(转) 原文: http://www.jb51.net/article/56682.htm 背景: 微软的 .NET FRAMEWORK 现在 ...
- unity3d占用内存太大解决方法
原帖:http://www.onevcat.com/2012/11/memory-in-unity3d/ 转载自星辰 Unity3D占用内存太大的解决方法 最近网友通过网站搜索Unity3D在手机及其 ...
- hashmap value占用空间大小_求比HashMap占用内存少的查找方法
我用MAT工具试了一下,发现我的感觉可能有问题. 我比较了一下Hashmap和两个String数组的内存情况(479个key,value对,String的长度都比较小(1-5) ),MAT的统计结果如 ...
- (转)C# Winform应用程序占用内存较大解决方法整理
背景: 微软的 .NET FRAMEWORK 现在可谓如火如荼了.但是,.NET 一直所为人诟病的就是"胃口太大",狂吃内存,虽然微软声称 GC 的功能和智能化都很高,但是内存的回 ...
- mysql占用内存过高调优方法
优化mysql数据库性能的十个参数 (1).max_connections: 查看对应信息:show variables like '%max_connections%'; 允许的同时客户的数量.增加 ...
最新文章
- ORACLE网络连接配置与文件:listener.ora、sqlnet.ora、tnsnames.ora
- 蓝桥杯-表达式计算(java)
- 论文浅尝 | CFO: Conditional Focused Neural Question Answering
- 【晒出你的第83行代码】剑指星辰,两位开发者贴出了小试牛刀的毕设代码
- (三.0)通过FPGA实现以太网通信原理及理解
- ssh远程访问失败 Centos7
- 替代传统按键方案 单通道感应TTP223E-BA6 TTP223E-CA6 TTP223E-HA6 单按键触摸检测IC
- 深度置信网络(DBN)
- Linux更新清华源
- c语言编程三次方程,c语言求三次方程的根程序设计
- 美化你的Xfce桌面
- Django项目部署至华为云服务器
- 钉钉、飞书、企业微信,还没学会赚钱
- vs2013编译报错,未能将obj/..复制到bin/..,bin/...文件正被另一进程时候用
- 全国表彰|达观数据创始人陈运文博士荣获第十一届“中国青年创业奖”,是上海唯一获奖者
- Android Google Map 开发指南(一)解决官方demo显示空白只展示google logo问题
- vue-cli项目局域网访问
- Dell BIOS/CMOS设置诠释
- 22年前的9月14日中国发出的第一封电子邮件
- otn 709帧结构
热门文章
- 【dfs】病毒(jzoj 1284)
- 你知道面试官是如何刷人的吗
- art-template入门(一)之介绍
- HikariCP-史上最快速的连接池
- 【php】正则无法截取\反斜杠的解决方法
- java中的Queue队列的用法
- 某同学正为自己安装不上sqlserver数据库而愁眉苦脸,使用朋友给的方法顿时喜笑颜开,那么朋友到底出了个什么样的方法呢?...
- ssm(Spring+Spring mvc+mybatis)Service层接口——IDeptService
- java中判断 101-200 之间有多少个素数,并输出所有的素数
- Ajax传递json数据