天道酬勤,学无止境

EnumMap 可能被认为是 Java bean 的合理替代品吗?(Might EnumMap be considered a reasonable alternative to Java beans?)

问题

好奇是否有人考虑过使用 EnumMap 代替 Java bean,尤其是“值对象”(没有行为)? 在我看来,一个优势似乎是“属性”的名称可以直接从支持的 Enum 访问,而无需反射,因此我认为它会更快。

回答1

可能比使用反射快一点(我没有测量它,也没有在谷歌中找到任何指标); 但是这种方法有很大的缺点:

  1. 您正在失去类型安全性。 而不是int getAge()String getName()一切都是Object get(MyEnum.FIELD_NAME) 。 这将提供一些丑陋的代码和运行时错误。

  2. 我们喜欢和喜欢的所有 javabean 细节(例如,属性级注释)都消失了。

  3. 由于您根本没有任何行为,因此这种方法的适用性似乎相当有限。

底线是 - 如果你真的需要所谓的:-) 性能提升(你必须测量它以证明它存在),这在非常特定的情况下可能是一种可行的方法。 它是整个 javabean 的可行替代方案吗? 绝对不是。

回答2

一个 bean 意味着是可变的,因此 setter 方法。 EnumMap 在速度上与使用整数作为 Key 的 HashMap 相当,但 Key 是不可变的。 Beans 和 EnumMaps 有两种不同的用途。 如果所有的 Key 在设计时都是已知的并且保证永远不会改变,那么使用 EnumMap 就可以了。
更新 bean 比更改 EnumMap 的支持 Enum 要简单得多,而且在下游代码中创建错误的可能性要小得多。

回答3
Record set(Thing, a) 458 ms Bean setThing(a) 278 ms Record get(Thing) 398 ms Bean getThing 248 ms
回答4

我不明白如何使用 EnumMaps 删除“类分析”。 除非您有一个具有 20 多个属性的通用枚举可以重用于每个“bean”,否则您仍然在发明一个枚举以用于每个枚举映射,例如

public enum PersonDTOEnum {
     A, S, L;
}

class Person {

    int a;
    int s;
    String l;

    // getters + setters elided
}

更不用说现在一切都是字符串了。

回答5

我之前没有指定这个,但我正在使用 ResultSet。 因此,为了完整起见,我想提供这个答案。

Commons/BeanUtil 的“RowSetDynaClass”可能是与具体 bean 相关的过多样板和 EnumMap 的限制之间的快乐媒介

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Might EnumMap be considered a reasonable alternative to Java beans?
    Curious if anybody has considered using EnumMap in place of Java beans, particularly "value objects" (with no behavior)? To me it seems that one advantage would be that the name of a "property" would be directly accessible from the backing Enum, with no need for reflection, and therefore I'd assume it would be faster.
  • Java枚举:两种枚举类型,每种包含彼此的引用?(Java Enums: Two enum types, each containing references to each other?)
    问题 有没有一种方法可以解决由两个互相引用的枚举引起的类加载问题? 我有两组枚举Foo和Bar,它们的定义如下: public class EnumTest { public enum Foo { A(Bar.Alpha), B(Bar.Delta), C(Bar.Alpha); private Foo(Bar b) { this.b = b; } public final Bar b; } public enum Bar { Alpha(Foo.A), Beta(Foo.C), Delta(Foo.C); private Bar(Foo f) { this.f = f; } public final Foo f; } public static void main (String[] args) { for (Foo f: Foo.values()) { System.out.println(f + " bar " + f.b); } for (Bar b: Bar.values()) { System.out.println(b + " foo " + b.f); } } } 上面的代码作为输出产生: A bar Alpha B bar Delta C bar Alpha Alpha foo null Beta foo null Delta foo null 我知道为什么会发生
  • 使用 enum.values() 与 String 数组时是否会降低性能?(is there a performance hit when using enum.values() vs. String arrays?)
    问题 我正在使用枚举来替换我的 java 应用程序(JRE 1.5)中的String常量。 当我在不断调用的方法中(例如在呈现 UI 时)将枚举视为名称的静态数组时,是否会影响性能? 我的代码看起来有点像这样: public String getValue(int col) { return ColumnValues.values()[col].toString(); } 说明: 我担心与重复枚举values()相关的隐藏成本(例如,在paint() 方法内部)。 我现在可以看到我的所有场景都包含一些int => enum转换 - 这不是 Java 的方式。 提取values()数组的实际价格是多少? 它甚至是一个问题吗? 安卓开发者 阅读下面的 Simon Langhoff 的回答,Geeks On Hugs 早些时候在接受的回答评论中指出了该回答。 Enum.values()必须做一个防御性的副本 回答1 Enum.values()为您提供对数组的引用,迭代枚举数组的成本与迭代字符串数组的成本相同。 同时,将枚举值与其他枚举值进行比较实际上比将字符串与字符串进行比较要快。 同时,如果您担心调用values()方法而不是已经拥有对数组的引用的成本,请不要担心。 Java 中的方法调用(现在)非常快,并且任何时候它对性能有实际影响,方法调用无论如何都会被编译器内联。 所以,说真的
  • 是否有任何原因EnumMap和EnumSet不可导航(Is there any reason EnumMap and EnumSet are not Navigable)
    问题 枚举是可比的,这意味着您可以 NavigableSet<AccessMode> modes = new TreeSet<>(); NavigableMap<AccessMode, Object> modeMap = new TreeMap<>(); 这些具有O(ln N)访问时间。 枚举集合具有O(1)访问时间,但不可导航 NavigableSet<AccessMode> modes = EnumSet.noneOf(AccessMode.class); // doesn't compile NavigableMap<AccessMode, Object> modeMap = new EnumMap<>(AccessMode.class); // doesn't compile 我想知道是否有一个原因,枚举集合不可导航(和排序)。 即我想念什么吗? 回答1 我最好的猜测是,可导航性并未被视为枚举集的主要用例。 在实现中,没有什么会阻止可导航性。 TreeSet和TreeMap涵盖了将一组枚举成员的需要与可导航性结合在一起的罕见用例。 回答2 JDK及其各种API缺少许多“显而易见的”功能。 为什么忽略/遗忘了此特定功能? 我们只能猜测。 但是您的问题很长时间以来一直是Sun / Oracle的RFE: http://bugs.sun.com/bugdatabase/view
  • 番石榴中是否有相应的不可变 enumMap ?(Is there a corresponding immutable enumMap in guava?)
    问题 我最近了解了 EnumMap 在 Java 中的好处,并想将现有的ImmutableMap<OccupancyType, BigDecimal>替换为 EnumMap。 但是,我也喜欢 ImmutableMap 提供的不可变属性。 番石榴中是否有变体 ImmutableEnumMap 可用? 在存储方面哪一个(EnumMap vs ImmutableMap)表现更好? 我找不到两者的比较。 如果有人可以指出我的链接或对两种数据结构的效率提供一些见解,我将不胜感激? 回答1 番石榴贡献者在这里。 Guava 目前没有ImmutableEnumMap变体,但如果有,它可能只是一个EnumMap的包装器。 (也就是说,稍微好一点的不可变实现是可能的。) 在任何情况下, EnumMap都会比基本的ImmutableMap表现得更好; 很难或不可能被击败。 (不过,我将提交一个问题来调查为枚举键类型添加ImmutableMap变体。) 更新:Guava 14 添加了 Maps.immutableEnumMap()。 回答2 我只是想提供一个例子,因为ImmutableEnumMap在 Guava 14.0 中,因为它是一个包私有类,所以你不能做ImmutableEnumMap.of() 。 您必须改为执行Maps.immutableEnumMap() 。 private final
  • 如何在 Java 的 Lambda API 中构建复制函数的 Map(How to build a Map that replicates a Function in Java's Lambda API)
    问题 从将一对Enum映射到一个值的java.util.function.BiFunction ,我想构建一个反映该映射的EnumMap 。 例如,让E1和E2为enum类型,而T任何给定类型: BiFunction<E1,E2, T> theBiFunction = //...anything EnumMap<E1,EnumMap<E2,T>> theMap = buildTheMap( // <-- this is where the magic happens E1.values(), E2.values(), theBiFunction); 给定任意一对E1和E2类型的值 E1 e1 = //any valid value... E2 e2 = //any valid value.... 以下两个值应相等: T valueFromTheMaps = theMap.get(e1).get(e2); T valueFromTheFunction = theBiFunction.apply(e1,e2); boolean alwaysTrue = valueFromTheMaps.equals(valueFromTheFunction); 对于发生“魔术”的方法,最好的(更优雅、更高效等)的实现是什么? 回答1 如果您使用通用解决方案并将其分解,您将获得一个优雅的解决方案。 首先
  • Java枚举相对于旧的“ Typesafe枚举”模式的优势?(Advantages of Java's enum over the old “Typesafe Enum” pattern?)
    问题 在JDK1.5之前的Java中,“ Typesafe Enum”模式是实现只能接受有限数量的值的类型的常用方法: public class Suit { private final String name; public static final Suit CLUBS =new Suit("clubs"); public static final Suit DIAMONDS =new Suit("diamonds"); public static final Suit HEARTS =new Suit("hearts"); public static final Suit SPADES =new Suit("spades"); private Suit(String name){ this.name =name; } public String toString(){ return name; } } (例如,参见Bloch的Effective Java中的第21项)。 现在在JDK1.5 +中,“官方”方法显然是使用enum : public enum Suit { CLUBS("clubs"), DIAMONDS("diamonds"), HEARTS("hearts"), SPADES("spades"); private final String name
  • 枚举
    枚举 枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常数。枚举在曰常生活中很常见,例如一个人的性别只能是“男”或者“女”,一周的星期只能是 7 天中的一个等。类似这种当一个变量有几种固定可能的取值时,就可以将它定义为枚举类型。 在 JDK 1.5 之前没有枚举类型,那时候一般用接口常量来替代。而使用 Java 枚举类型 enum 可以更贴近地表示这种常量。 声明枚举 声明枚举时必须使用 enum 关键字,然后定义枚举的名称、可访问性、基础类型和成员等。枚举声明的语法如下: enum-modifiers enum enumname:enum-base { enum-body, } 其中,enum-modifiers 表示枚举的修饰符主要包括 public、private 和 internal;enumname 表示声明的枚举名称;enum-base 表示基础类型;enum-body 表示枚举的成员,它是枚举类型的命名常数。 任意两个枚举成员不能具有相同的名称,且它的常数值必须在该枚举的基础类型的范围之内,多个枚举成员之间使用逗号分隔。 使用枚举还可以使 switch 语句的可读性更强,例如以下示例代码: enum Signal { // 定义一个枚举类型 GREEN,YELLOW,RED } public class TrafficLight { Signal color
  • 深入了解和学习Java枚举Enum
    文章目录 深入了解和学习Java枚举Enum枚举类概念枚举类的由来反编译JAVA枚举类枚举类的主要方法枚举类对接口的实现方式枚举类统一实现抽象方法枚举对象分别实现接口中的抽象方法 EnumMap用法EnumSet用法枚举类与 Switch 的配合使用利用枚举实现单例模式利用Java枚举实现策略模式参考源代码 深入了解和学习Java枚举Enum 枚举类概念 一个类的对象是有限个,确定的,我们称此为枚举类。 当需要定义和维护一组常量时,强烈建议使用枚举类。 如果一个枚举类中只有一个对象,则可以作为单例模式的实现方式(用枚举实现单例模式)。 枚举类的由来 讲完上面的概念可能很多初学者会很懵逼,到底什么是枚举类啊,为什么要有枚举类啊,它跟普通类的区别是什么? 我们把枚举类这个概念抛开,因为枚举类是从JDK1.5才出现的,所以我们来看看那在JDK1.5之前我们是怎么设计这一个特殊的类的(包含固定实例数量的特殊类) 我们常常使用抽象类或者接口来维护一些常量(因为无法实例化对象),比如如下: package org.example; public abstract class CalendarConstant { public static final int YEAR = 1; public static final int MONTH = 2; } public interface
  • 有没有一种类似C的方式从Java枚举中获取项目编号?(Is there a a C-like way to get item number from enum in java?)
    问题 也许这是一个简单的基本问题 有一个枚举 public enum TK{ ID,GROUP,DATA,FAIL; } 我可以获取订单号,例如ID = 0,GROUP = 2,DATA = 3,FAIL = 4吗? 这是达到此目的的一种方法,但又是一个奇怪而漫长的方法! = S public enum TK{ ID(0),GROUP(1),DATA(2),FAIL(3); int num; TK(int n) { this.num=n; } public int get() { return num; } }; 获取数字,所以我写TK.ID.get(),TK.GROUP.get()等...我不喜欢 有一个更好的方法? (C枚举,C宏..我都想念你们) 谢谢 回答1 您在寻找序数吗? 回答2 ordinal()做您想做的事。 这是该文档的摘录: 返回此枚举常量的序数(其在enum声明中的位置,其中初始常量的序数为零)。 大多数程序员都不会使用这种方法。 它设计用于供基于EumSet和EnumMap的复杂的基于枚举的数据结构使用。 “有效Java 2nd Edition”中的Josh Bloch进一步解释了为什么使用ordinal()是一个糟糕的主意。 以下是一些引号,略作编辑: 永远不要从其序数中得出与枚举相关的值; 而是将其存储在实例字段中。 (第31项:使用实例字段代替序数
  • java:Map 或 EnumMap 的 PropertyChangeSupport?(java: PropertyChangeSupport for Map or EnumMap?)
    问题 是否有 java.beans.PropertyChangeSupport 或 com.jgoodies.binding.beans.ExtendedPropertyChangeSupport 的版本有助于支持 Map 或 EnumMap 中的更改侦听器? (具有已知有限键和更改映射中所有值的侦听器的键值存储) 我真的不需要 bean 类型的访问权限,我有许多不同的统计信息,例如: interface hasName() { public String getName(); } enum StatisticType implements hasName { MILES_DRIVEN, BURGERS_SERVED, CUSTOMERS_HELPED, BIRDS_WATCHED; @Override public String getName() { return name(); } } 我想发布一个界面,如: interface KeyValueStore<K extends hasName,V> { void setValue(K key, V value); V getValue(K key); void addPropertyChangeListener(PropertyChangeListener listener); void
  • Java中基于枚举的表/矩阵(Enum based table/matrix in Java)
    问题 我有两个枚举:3 个值的level和 4 个值的criticality值。 这两个映射的组合映射到priority枚举中的 8 个值之一。 该映射是非线性的,将来可能会发生变化。 实现具有级别和关键性并输出优先级的静态函数的最佳*方法是什么? *最好是易于阅读和理解,易于更改且安全,而不是性能猪。 考虑到输入域将来可能发生变化的解决方案的额外积分。 到目前为止我考虑的方式: 嵌套 switch..case 。 许多行和大量样板代码。 如果您忘记在案例中返回值,也容易出错。 基本上代码如下所示: switch (bc) { case C1: switch (el) { case E1: return EmergencyPriority.P1; case E2: return EmergencyPriority.P2; case E3: return EmergencyPriority.P3; } case C2: switch (el) { case E1: return EmergencyPriority.P2; case E2: return EmergencyPriority.P3; case E3: return EmergencyPriority.P4; } case C3: switch (el) { case E1: return
  • Java枚举-在定义字段之前无法引用它(Java enum- Cannot reference a field before it is defined)
    问题 我有一个像下面这样的枚举,但是蚀说每个相对的对的第一个定义中都有错误。 public enum Baz{ yin(yang), //Cannot reference a field before it is defined yang(yin), good(evil), //Cannot reference a field before it is defined evil(good); public final Baz opposite; Baz(Baz opposite){ this.opposite = opposite; } } 我想做到的是能够使用Baz.something.opposite获得的另一对象Baz.something 。 有没有可能的解决方法? 也许在此示例中定义了一个空的占位符,表示yang和bad然后定义yin和good ? 回答1 您可以尝试类似的方法: public enum Baz{ yin("yang"), yang("yin"), good("evil"), evil("good"); private String opposite; Baz(String opposite){ this.opposite = opposite; } public Baz getOpposite(){ return Baz.valueOf(opposite)
  • 将标志传递给对象的正确设计模式(Proper design pattern for passing flags to an object)
    问题 在C中我做过这种事情 enum { USE_COKE = 1, USE_PEPSI = 2, USE_JUICE = 4, USE_WATER = 8 }; int makeDrink(int flags); //... int rcode = makeDrink(USE_COKE | USE_JUICE | USE_WATER); 我知道这是非常标准的,例如,它也用于iostream 。 我想知道如何将这种设计模式翻译成 Java 或 OOP? 我很确定多态不是这里的方法,因为我的代码有一个if(flag_is_set)块比重写大部分例程更好。 是否有实用程序Flags类,或者使用配置对象、 enum或一堆整数等的首选方法? 回答1 Java有枚举。 这是教程。 我会在整数等上使用这些。这是一个类型安全的解决方案,并且由于枚举是对象,您可以附加行为并避免使用switch语句。 您可以使用 EnumSet 组合这些(如上)。 从文档: 用于枚举类型的专用 Set 实现....这种表示非常紧凑和高效。 这个类的空间和时间性能应该足够好,以允许它用作传统的基于 int 的“位标志”的高质量、类型安全的替代品。 回答2 Brian Agnew 的答案是正确的。 Java 有一个强大、灵活且非常方便的 Enum 工具。 (不要与现在过时的 Enumeration 接口混淆。)
  • Spring Java 配置 - 如何创建枚举到 bean 引用的映射(Spring Java Configuration - how do create a map of enums to beans-references)
    问题 使用基于 Java 的配置,我正在尝试将映射枚举到 bean 引用的映射转换为纯 Java 配置(目前在 XML 和作品中),但似乎无法在文档中找到任何内容; 目前,我的 XML 是这样的; <util:map id="colourHanders" key-type="com.example.ColourEnum" value-type="com.example.ColourHandler"> <entry key="white" value-ref="whiteColourHandler"/> <entry key="blue" value-ref="blueColourHandler"/> <entry key="red" value-ref="redColourHandler"/> </util:map> 我确信这很容易,但同样,找不到关于如何在纯 Java 中表示这一主题的任何内容(所以我没有任何 XML 配置文件)。 笔记; ColourHandler bean 是使用 @Component 注释创建的,例如。 @Component public class RedColourHandler implements ColourHander{ ..... } 并且 colorHandlers 的映射是这样引用的; @Resource(name=
  • 【Java基础】分析Map接口常用实现类
    文章目录 Java集合架构图Map接口简介Map接口的基本操作Map接口直接或者间接的实现类HashMapHashtableLinkedHashMapTreeMapWeakHashMapEnumMapIdentifyHashMapConcurrentHashMap 四种遍历Map接口的方式 ==比较的是地址值,而不是HashCode,所以这里以后千万不要掉进误区了。!!! Java集合架构图 点击放大查看 List , Set, Map都是接口,List , Set继承至Collection接口(Collection继承至Iterable),Map为独立接口 Map接口简介 Map不是collection的子接口或者实现类。Map是一个接口。 Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 值可以相同,但键肯定是唯一的 Map 接口最流行的几个实现类是HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用) Map接口的基本操作 方法描述int size()获取Map集合大小(即元素数量)boolean isEmpty()判断是否为空boolean containsKey(Object key)判断是否包含某个键boolean containsValue(Object value
  • 深入了解Java枚举类
    文章目录 深入理解枚举类简介枚举的好处枚举的典型应用使用规范 枚举的本质枚举类的声明 枚举的方法枚举的特性基本特性枚举可以添加方法枚举可以添加普通方法、静态方法、抽象方法、构造方法枚举可以实现接口 枚举的应用组织常量状态机错误码组织枚举 枚举工具类EnumSetEnumMap 参考资料 深入理解枚举类 简介 enum 全称是 enumeration,是 JDK1.5 引入的新特性,位于Java.lang 包下。 在Java中 enum 是一个关键字,被 enum 修饰的类型就是枚举类。 public enum ColorEnum{ BLACK,WHITE,GREEN; } 枚举的好处 将枚举类型用作set或map的类型时,专用且高效。(引自枚举类的介绍) 枚举的典型应用 如 状态码、常量、颜色、类别等 使用规范 枚举类名带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。 正例:枚举名字为ProcessStatusEnum的成员名称:SUCCESS / UNKNOWN_REASON所有的枚举类型字段必须要有注释,说明每个数据项的用途 引自阿里巴巴开发手册 枚举的本质 枚举类的声明 package java.lang; public abstract class Enum<E extends Enum<E>> implements Comparable<E>
  • 如何实现连通房?(How to implement connected rooms?)
    问题 这可能是一个重复的问题,因为我不知道用词组搜索查询。 我正在用 Java 创建一个类似 Zork 的基于文本的游戏,其中角色移动到相互连接的不同房间。 我希望能够列出玩家可用于该房间的所有选项。 例如,房间 A 东连 B,B 西连 A,南连 C,北连 D,依此类推。 我应该使用什么数据结构或者我应该如何尽可能有效地实现它? 回答1 首先要决定的是什么构成了有效的方向:它是来自固定列表还是可以是自由格式的文本? 最简单的解决方案是拥有四个基本方向。 有些人建议将其作为 int 数组来执行。 这可能是 C/C++/C# 中的有效解决方案(它们中的枚举都只是 int 常量),但没有理由在 Java 中这样做。 在Java中,你可以使用(类型安全)枚举这亦可以有状态和行为,并使用EnumMap的,这是高效的。 在内部,它只是一个由枚举序数值索引的数组。 你可能会争辩说这和 int 数组有什么区别? 答案是EnumMap中的 int 数组是类型安全随机访问集合的内部实现细节。 如果允许退出方向的自由格式文本,您的结构将如下所示: Map<String, Direction> exits; 不过我不推荐这个。 我建议列举可能的方向: public enum Direction { NORTH("north", "n"), NORTHWEST("northwest", "nw"),
  • 在java中以枚举方式将整数值存储为常量[重复](Storing integer values as constants in Enum manner in java [duplicate])
    问题 这个问题在这里已经有了答案: Java:在声明带有整数常量的枚举时遇到问题3 个回答 3年前关闭。 我目前正在以下列方式创建整数常量。 public class Constants { public static int SIGN_CREATE=0; public static int SIGN_CREATE=1; public static int HOME_SCREEN=2; public static int REGISTER_SCREEN=3; } 当我尝试以枚举方式执行此操作时 public enum PAGE{SIGN_CREATE,SIGN_CREATE,HOME_SCREEN,REGISTER_SCREEN} 当我使用PAGE.SIGN_CREATE它应该返回 1; 回答1 好吧,你不能完全那样做。 PAGE.SIGN_CREATE永远不会返回 1; 它将返回PAGE.SIGN_CREATE 。 这就是枚举类型的意义所在。 但是,如果您愿意添加一些按键,则可以向枚举添加字段,如下所示: public enum PAGE{ SIGN_CREATE(0), SIGN_CREATE_BONUS(1), HOME_SCREEN(2), REGISTER_SCREEN(3); private final int value; PAGE(final int
  • Java 8 列表到 EnumMap 与总和(Java 8 List to EnumMap with sums)
    问题 我有以下课程: public class Mark { private Long id; private Student student; private Integer value = 0; private Subject subject; } public enum Subject { MATH, CHEMISTRY } 我必须接收EnumMap<Subject, Integer> ,其中的值是来自Mark的所有值的总和。 List<Mark>示例: Mark(..., value = 1, subject = MATH) Mark(..., value = 2, subject = MATH) Mark(..., value = 5, subject = CHEMISTRY) 有了这个值,我必须收到以下EnumMap : 数学 -> 3 化学 -> 5 我认为应该用Collectors::groupingBy来完成,但我不明白如何获得EnumMap和他的价值。 回答1 markList.stream().collect( groupingBy( Mark::getSubject, () -> new EnumMap<Subject, Integer>(Subject.class), summingInt(Mark::getValue)));