首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何避免将对象id作为映射中的键以及对象本身内的键?

如何避免将对象id作为映射中的键以及对象本身内的键?
EN

Software Engineering用户
提问于 2016-12-27 20:13:07
回答 3查看 708关注 0票数 1

我使用JSON映射来保存id是映射键的对象(例如,用户),但是对象(用户)本身也包含id。

JSON

代码语言:javascript
复制
{
   "john":{
      "username":"john",
      "age":30
   },
   "bob":{
      "username":"bob",
      "age":40
   },
   "chris":{
      "username":"chris",
      "age":50
   }
}

代码语言:javascript
复制
class user {
   String username;
   Integer age;

   getUsername() {
      return username;
   }
}

我想使用映射轻松地检索对象,但同时我不希望ids作为映射中的键和对象的属性。最干净的解决方案是什么?

我可以想到以下解决方案:

  1. 不要使用地图,而要使用列表。但是访问元素需要对列表进行迭代,我不能使用简单的get(K key)方法。
  2. 不要将用户名保存在对象中,但是getUsername()将需要知道它保存在映射中的位置,这将是非常糟糕的耦合。
  3. 对用户名使用枚举,但是不能从JSON动态读取用户。
EN

回答 3

Software Engineering用户

发布于 2016-12-28 09:38:38

用户是应用程序的一个实体,因此它应该包含代表实际用户的所有必要字段。

用户实体与您在整个应用程序中用于性能、显示、持久化等的各种结构完全无关。集合中的元素不应该知道它们所在的集合。仅仅因为一个映射需要一个键来存储一个值,这并不意味着你必须对这个值做些什么来删除重复。

你想得太多了。在JSON表示中使用用户名是没有问题的。随着应用程序的发展,您将看到使用实体而不是单个字段使您的API/代码更加直观。

票数 4
EN

Software Engineering用户

发布于 2016-12-28 00:01:17

考虑把你的顾虑分开。现在,您正在保存索引数据。然而,数据的索引是一个实现细节。如果你发现你根据年龄检索的频率足够多,以至于你想要根据年龄索引呢?

相反,将其保存为数组,并在加载数据时执行索引。将数据处理成内存中有用的结构,在内存中复制是可以接受的。保存时,删除复制。这样可以将保存到磁盘或通过有线传输的信息量降到最低。记住,即使在今天,CPU比磁盘快一个数量级,比互联网快一个数量级。

票数 3
EN

Software Engineering用户

发布于 2016-12-28 12:56:18

首先,让我说,我完全同意@Bogdan和@KevinFee提供的答案。话虽如此,我的答覆只会扩展他们的答覆,就你如何做到这一点提出建议。

考虑采用以下方法:

代码语言:javascript
复制
class User
{
    public int Age { get; set; }
}

class IdentifiedUser : User 
{
    public string Username { get; set; }

    public IdentifiedUser(User user, string username)
    {
        Username = username;
        Age = user.Age;
    }

    public User CreateUser()
    {
        return new User
        {
            Age = this.Age
        };
    }
}

class UserRepository
{
    public Dictionary<string, User> Repository = new Dictionary<string, User>();

    public void AddUser(IdentifiedUser identifiedUser)
    {
        Repository.Add(identifiedUser.Username, identifiedUser.CreateUser());
    }

    public IdentifiedUser GetUser(string username)
    {
        return new IdentifiedUser(Repository[username], username);
    }
}

显然,我忽略了一些好的实践,比如在字典中检查键是否存在,因为我想把重点放在手头的问题上。

这里的想法是拥有一个没有冗余信息的对象的存储库,但也提供一种机制,向外部世界提供这些对象所包含的标识数据。这也可以通过关联而不是继承来实现。这样,您可以最大限度地减少磁盘空间,代价是CPU开销可以忽略不计。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/338937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档