我正在尝试创建一个(如果可能的话)一个类似数据库的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。 - 平均每行的顺序列。
- 插入新行。
但我认为你的立场想法可能更适合你的情况。