数据定义和业务操作
数据结构和业务操作
需求
新闻标签是发布新闻的用户可以给新闻添加的说明数据,假设用户可添加1~3个标签,包括自定义标签和系统标签。系统标签是应用预定义的标签,供用户选择。用户也可以自己输入自定义标签。
数据定义
-
标签分类:
标签的类别。系统标签都有它的分类,比如“体育”、“电影”...等。
自定义标签属于“自定义”分类。 -
标签:
用于对新闻进行附加说明的“文本内容”,例如说明新闻的核心内容的关键字,话题细分标题。
数据抽象
模型类
从oop的角度,分别设计TagCategory、Tag两个类。
class TagCategory {
String name;
int type;
int id;
}
class Tag {
String name;
int type;
int id;
}
如果认为"标题分类"、“标签”可以简单到仅仅是一个String,那么好像没有必要设计TagCategory、Tag类。但从业务发展上,这样很容易陷入误区:
假设系统标签针对不同用户、不同类型用户是不同的,在未来,某些情况下,又会变成很可能存在不同的标签分类、或标签的名称相同这样的情况。
所以,我们总是设计类拥有id,它表示一个业务无关的唯一性,对应一个“数据实体”,类似于数据库中的一条记录就是一个实体。在Java中,不同对象具有相同id那么就是相同的记录。
而更多业务方面的“相等性”是根据和业务人员商定下来的模型的其它字段共同决定的。
另一方面,假设用String来表示分类和标签——那么有关分类和标签的数据都是体现在对应变量的名称上,而没有任何类型信息:
ArrayList<String> mTagCategories;
ArrayList<String> mAllTags;
HashMap<String, ArrayList<String>> mTagData;
上面的数据结构都是基本类型,这意味着我们无法为期望的数据模型增加额外的功能——为类增加方法那样。
class TagCategory {
String name;
int type;
int id;
ArrayList<String> tags;
}
class Tag {
String name;
int type;
int id;
TagCategory category;
}
如果是面向对象的定义,标签分类和标签应该像上面那样。
分类和标签的关联:数据库和OOP的不同方式。
OOP和关系型数据库是两种不同的设计思路,想象下多少ORM做的事情:对象关系映射,就是把表之间的记录的1对1、1对多、多对1关系转变为对象之间的引用。
像Tag在数据库里,需要使用categoryId来表示关联的分类,而在Tag对象,直接使用字段存储指向对应TagCategory对象的引用即可。
一些情况下:我们得到Tag对象的时候,并没有TagCategory对象存在——也不关心它的使用,那么从Tag对象数据的晚自性上看,它还是需要一个int categoryId来像数据库表的设计那样,存储着对应TagCategory的信息。
事情还有最后的解决方案:
类似数据库中“用户”、“权限”表那样,使用一个额外的表来存储用户和权限之间的关联。
可以让TagCategory的List<Tag> tags
来仅单向存储TagCategory包含的Tag集合,而根据Tag找到对应分类的操作需要额外的方法来完成。Tag中是否保存对应的TagCategory的信息? 如果Tag数据经常出现在无对应TagCategory的上下文中,而又需要知道它的TagCategory,那么就必须存储对应的
categoryId了。
业务操作
对应服务器返回的系统标签数据集合,我们在使用的时候有若干方式:
1. 得到标签分类的列表。
2. 得到某个标签分类下的标签列表。
3. 对于任意的标签,得到它的分类。
4. 得到所有标签的集合。
5. 根据标签id找到标签。
这里涉及到列表和查询。
一般的,我们从服务器返回的json数据是一个个嵌套的Map对象。
{
"newsTags":[
{
"categoryName":"分类1",
"tagList":[
{
"tagName":"标签1",
"tagId":"1",
"tagType":"hot"
},
{
"tagName":"标签2",
"tagId":"2",
"tagType":"spot"
}
]
},
...
]
}
上面的数据结构对应返回完整的具备“分类”的标签数据是非常合适的。
在解析完成之后,需要形成TagCategory的List,每个TagCategory对象本身包含它拥有的Tag的List。
作为“字典”数据,如果系统中很多操作都需要根据以上的分类、标签数据来完成一些查询操作,如3和5,如果我们拥有List<TagCategory>
和List<Tag>
,那么通过遍历列表可以完成任务。
问题是当查找操作很频繁,那么每次都去循环就很低效。
可以对List进行排序,然后提升查找的效率。
标签数据量不大时,可以使用Map来存储标签的id及其对应的Tag对象,这样通过id找到Tag对象就很高效了,List和Map前者注重顺序,后者注重查询。
假设我们有300个系统标签,现在有10个tagId,需要转换为对应的Tag对象,使用Map要远比查找List高效的多。
所以,在业务操作不同时,根据数据规模适当选择合适的数据结构来存储数据。
待考量
假设西瓜重量在12-30斤,一个桶100斤,设计算法,对应给定的100个西瓜,使用最少的桶装完。
这个的实际应用是:
标签云在显示的时候需要自动换行,如果希望标签的排列紧凑一些,怎么用最少的行数显示所有标签?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人