我正在尝试创建(如果可能)数据库的LinkedList。
我的想法是,我添加到表中的数据将需要具有复杂的订单结构,因为当我添加新项目时,可以将其添加到列表中的任何位置。
例如,如果我有一个包含项目(1),(2),(3),(4),(5)的列表。我可以在位置(2)上直接添加一个新项目,从而更改整个列表(或至少更改位置(2)上该项目之后的元素)。
为此,我必须考虑的另一件事是,每个项目都必须知道他先前项目的ID(不是索引,而是从服务器获取的一些自定义ID)。当我还必须重新排序服务器上的列表时,实际上将需要此ID(当我上载项目时,还必须发送具有先前ID的订购请求)。
目前,我的文档模型如下所示:
@DatabaseTable(tableName = DocumentsTable.TABLE_NAME, daoClass = DocumentDao.class)
public class Document implements Parcelable {
@DatabaseField(columnName = DocumentsTable.LOCAL_ID_COLUMN, generatedId = true, dataType = DataType.INTEGER)
int localId;
@DatabaseField(columnName = DocumentsTable.SERVER_ID_COLUMN, unique = true, dataType = DataType.STRING, useGetSet = true)
String serverId;
@DatabaseField(columnName = DocumentsTable.ALIAS_COLUMN, dataType = DataType.STRING, useGetSet = true)
String alias;
@DatabaseField(columnName = DocumentsTable.NAME_COLUMN, dataType = DataType.STRING, useGetSet = true)
String name;
@DatabaseField(columnName = DocumentsTable.DESCRIPTION_COLUMN, dataType = DataType.STRING, useGetSet = true)
String description;
@DatabaseField(columnName = DocumentsTable.OWNER_COLUMN, dataType = DataType.STRING, useGetSet = true)
String owner;
...
我在想添加两个新列,将其称为
prevDoc
和nextDoc
并将它们设置为Foreig键。像这样:@DatabaseField(columnName = DocumentsTable.PREVIOUS_DOC, foreign = true, canBeNull = true)
Document prevDoc;
@DatabaseField(columnName = DocumentsTable.NEXT_DOC, foreign = true, canBeNull = true)
Document nextDoc;
这样,表中的每个项目都将知道它的前一个项目应该是什么,下一个项目应该是什么。
但
现在我被困住了,在这一点上,我不知道如何才能正确地对它进行排序。另外,如何正确添加新项目?
新主意 ?
在这一点上,我认为我走错了路,似乎找不到一个好的解决方案。我在ORMLite文档中进行了搜索,但没有发现任何可以帮助我的东西。基本链接列表(例如数据库)的示例也对我没有帮助。我找到了一些图形数据库,但是我无法在Android中使用它们,而对于我的需求而言,它们却显得过分杀伤力。
最后的机会
作为最终解决方案,我添加了新列
orderPos
,我手动对其进行了更新:@DatabaseField(columnName = DocumentsTable.ORDER_POS, dataType = DataType.INTEGER, useGetSet = true)
int orderPos;
这是这样的用法:
对于每个项目,我设置一个orderPos值,该值在每个步骤中递增。
当我需要将项目添加到特定位置时,我将获得该项目之后的所有项目,并将它们的orderPos加1,然后再添加具有所需位置的orderPos的项目。
我知道这将涉及O(n-pos)+ 1的复杂性,但目前我再也没有想到。
请让我知道您的想法,以及如何使用ORMLite在Android上正确实现类似功能。
最佳答案
这样,表中的每个项目都将知道它的前一个项目应该是什么,下一个项目应该是什么。
是的,这有点奇怪。通常,这些字段将确定顺序,并且由于您要存储这些字段,因此只需使用qb.orderBy(...)
方法以任何顺序输出列表。
例如,如果我有一个包含项目(1),(2),(3),(4),(5)的列表。我可以在位置(2)上直接添加一个新项目,从而更改整个列表(或至少更改位置(2)上该项目之后的元素)。
因此,我假设您在位置2中插入了一个项目,但是如果您在位置2中插入了另一个项目,则先前的#2项目将变为#3。是的,那很难。
对于每个项目,我设置一个orderPos值,该值在每个步骤中递增。当我需要将项目添加到特定位置时,我将获得该项目之后的所有项目,并将它们的orderPos加1,然后再添加具有所需位置的orderPos的项目。我知道这将涉及O(n-pos)+ 1的复杂度
是的听起来不错。您可以使用1个SQL表达式进行更新,因此每个插入操作都需要2个SQL操作。除非表中有很多行,否则这不会太痛苦。
在框外思考,您可以做的一件事是使用Long
值的宽度。列表中的第一项为Long.MAX_VALUE / 2
。每当您插入列表时,都将获取左侧的排序值和右侧的排序值,并取它们的平均值。您必须在要插入的两个值的任一侧找到两个值,这将需要2个查询,但是您不需要更新所有行。
在我要插入的行中找到>=
行。如果没有,则Long.MAX_VALUE
。
在我要插入的行中找到<
行。如果没有,则为0。
平均每一行的订单列。
插入新行。
但我认为您的职位主张可能会更适合您的情况。