Java 集合中更好的类型安全性

发布于 2024-08-26 17:28:11 字数 494 浏览 5 评论 0 原文

在我的java编码中,我经常会得到几个 Map>Map> 然后我很难记住哪个字符串是哪个键。我用 //Map>//Map 注释该声明,但这不是最好的解决方案。如果 String 不是最终的,我会创建新类 CapabilityId extends StringGroupId extends String,但我不能。有没有更好的方法来跟踪哪个东西是关键并且也许让编译器强制执行它?

In my java coding, I often end up with several Map<String,Map<String,foo>> or Map<String,List<String>> and then I have trouble remembering which String is which key. I comment the declaration with //Map<capabiltyId,Map<groupId,foo>> or //Map<groupId,List<capabilityId>, but it's not the greatest solution. If String wasn't final, I would make new classes CapabilityId extends String and GroupId extends String, but I can't. Is there a better way to keep track of which thing is the key and maybe have the compiler enforce it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦与时光遇 2024-09-02 17:28:12

我会将其全部放在一个类中,并使用合理的字段/方法/参数名称。

public class GroupCapabilities {
    private Map<String, Map<String, Group>> groupCapabilities;

    public void addGroup(String capabilityId, Group group) {
        Map<String, Group> groups = groupCapabilities.get(capabilityId);
        if (groups = null) {
            groups = new HashMap<String, Group>();
            groupCapabilities.put(capabilityId, group);
        }
        groups.put(group.getId(), group);
    }

    public Map<String, Group> getGroups(String capabilityId) {
        return groupCapabilities.get(capabilityId);
    }

    public Group getGroup(String capabilityId, String groupId) {
        Map<String, Group> groups = groupCapabilities.get(capabilityId);
        return (groups != null) ? groups.get(groupId) : null;
    }

    // Etc..
}

这样您就可以在方法/参数名称中看到它期望/返回的内容。

I would put it all in single class and make use of sensible field/method/argument names.

public class GroupCapabilities {
    private Map<String, Map<String, Group>> groupCapabilities;

    public void addGroup(String capabilityId, Group group) {
        Map<String, Group> groups = groupCapabilities.get(capabilityId);
        if (groups = null) {
            groups = new HashMap<String, Group>();
            groupCapabilities.put(capabilityId, group);
        }
        groups.put(group.getId(), group);
    }

    public Map<String, Group> getGroups(String capabilityId) {
        return groupCapabilities.get(capabilityId);
    }

    public Group getGroup(String capabilityId, String groupId) {
        Map<String, Group> groups = groupCapabilities.get(capabilityId);
        return (groups != null) ? groups.get(groupId) : null;
    }

    // Etc..
}

This way the you can see at method/argument names what it expects/returns.

泡沫很甜 2024-09-02 17:28:12

有很多方法可以实现这一点(有些已经提到了):

  • 如@Roman,将通用类型包装在更具体的类型中,这可以提供更强的类型。强打字很好,IMO。
  • 作为@nanda,使用更具体的集合类型。 Java 库在这方面有点差。这取决于您对依赖关系的感受。
  • 作为@BalusC,将所有令人讨厌的东西移到一个令人讨厌的类中。并没有真正消除问题,但它确实包含了它(就像在《捉鬼敢死队》中一样)。
  • Map> 看起来非常像您有一个复合键,即包含两部分的键。因此,引入一个不可变的复合键类,即代表两个组件值对象的值对象。

There are a number of ways to go on this one (some already mentioned):

  • As @Roman, wrap the general purpose type in a more specific type, which gives stronger typing. Strong typing good, IMO.
  • As @nanda, use a more specific collection type. The Java library is a little poor in this area. It depends about how you feel about dependencies.
  • As @BalusC, move all the icky stuff into an icky class. Doesn't really remove the problem, but it does contain it (like in Ghostbusters).
  • Map<String,Map<String,foo>> looks very much like you have a composite key, i.e. a key that comprises two parts. So, introduce an immutable composite key class, that is a value object representing the two component value objects.
与之呼应 2024-09-02 17:28:12

Instead of Map<String,List<String>> you should use Multimap from Google Guava / Google Collection

http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/Multimap.html

逆光下的微笑 2024-09-02 17:28:12

添加到其他答案:

包装它。

这不仅是解决您的问题的方法,而且总体上是一个好主意,即避免简单的
参数。您的代码将获得可读性、健全性和可维护性。
您可以向其添加各种不错的属性,例如声明它@Immutable。正如您发现的那样,这种方式更容易记住和控制。您拥有班级并可以用它做任何您喜欢的事情。

Adding to the other answers:

Wrap it.

It is not just a solution to your problem but a good idea in general, i.e. avoid simple
parameters. Your code will gain readability, sanity and maintainability.
You can add all kinds of nice properties to it, e.g. declare it @Immutable. As you found out it this way is better to remember and to control. You own the class and can do whatever you like with it.

睫毛上残留的泪 2024-09-02 17:28:11

如果需要,可以将字符串包装在包装类中:

class GroupId implements Comparable {
   private String groupId;

   public GroupId (String groupId) {
       this.groupId = groupId;
   }
   ...
}

Map<GroupId, List<CapabilityId>> m = ...

Wrap strings in wrapper-classes if you want:

class GroupId implements Comparable {
   private String groupId;

   public GroupId (String groupId) {
       this.groupId = groupId;
   }
   ...
}

Map<GroupId, List<CapabilityId>> m = ...
笑看君怀她人 2024-09-02 17:28:11

CapabilityId 可以包含一个名为“id”的 String 字段,而不是让 CapabilityId 扩展 String;那么您的 Map 可以定义为 Map>,并且您可以通过 getId( ) 在你的关键类上。

我不确定我自己会这样做,但如果我这样做,我可能会这样做。

您可以通过使用带有 id 字段和 getId() 方法的 abstract GenericId 类来限制混乱,并具有 CapabilityIdGroupId 继承自它。

Instead of having CapabilityId extend String, CapabilityId could include a String field called "id"; then your Map could be defined as Map<CapabilityId, Map<GroupId, Foo>>, and you could get at the individual ID fields through a getId() on your key classes.

I'm not sure I would do this myself, but if I did, this is probably what I'd do.

You could limit the clutter by having an abstract GenericId class with an id field and getId() method, and have CapabilityId and GroupId inherit from it.

夜清冷一曲。 2024-09-02 17:28:11

创建一个可以子类化的 ID 类,该类由一个 String 字段以及 equals()hashCode() 的实现组成 使用该字段。

Create an ID class which you can subclass, and which consists of a String field and implementations of equals() and hashCode() which use that field.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文