我有一段旧项目的代码。
逻辑(高级别)如下:
用户发送一系列{id,Xi}
,其中id是数据库中对象的主键
目的是更新数据库,但Xi
值系列始终唯一。
即。如果用户发送{1,X1}
并且在数据库中我们有{1,X2},{2,X1}
输入应该被拒绝,否则我们最终会重复,即{1,X1},{2,X1}
,即我们在不同的行中有X1
两次。
在较低级别,用户发送一系列封装此信息的自定义对象。
目前,它的实现使用“强力”,即输入和jdbc结果集上的连续for循环,以确保唯一性。
我不喜欢这种方法,而且实际的实现有微妙的错误,但这是另一个故事。
我正在寻找一种更好的方法,无论是在编码还是性能方面。
我在想的是:
Set
。如果Set
的大小与列表不同,则用户的输入具有重复项。在那里。 HashMap<Long,String>
。关键是主键。 HashMap
没有contain
与ResultSet的行ID具有相同值的键,则将其添加到HashMap
HashMap
的值设为List
。如果它包含重复的拒绝输入。 这是我提出的算法。
有比这更好的方法吗? (我假设我对自己的算法没有错误)
答案 0 :(得分:3)
纯粹从性能的角度来看,为什么不让数据库弄清楚是否存在重复(如{1,X1},{2,X1}
)?在表中有一个唯一的约束,然后当update语句因抛出异常而失败时,捕获它并处理在这些输入条件下你想要做的事情。如果您需要回滚任何部分更新,您可能还希望将其作为单个事务运行。当然,这是假设您没有任何其他业务规则来推动您在此处未提及的更新。
使用您的算法,您花费了太多时间来迭代HashMap
和List
以删除重复的恕我直言。
答案 1 :(得分:1)
由于您无法更改数据库,如评论中所述。我可能会扩展你的Set想法。创建一个HashMap<Long, String>
并将数据库中的所有项目放入其中,然后创建一个HashSet<String>
,其中包含数据库中的所有值。
然后,当您浏览用户输入时,检查密钥对照散列图并查看值是否相同,如果它们是,那么很好,您不必做任何事情,因为确切的输入已经在您的数据库中。
如果它们不相同,则检查HashSet的值以查看它是否已存在。如果是,那么你有一个副本。
应该比循环更好。
对于多个更新,请执行从您的数据库创建的HashMap
的所有更新,然后再次检查Map
的值集,以查看其大小是否与密钥集不同。
可能有更好的方法可以做到这一点,但这是我得到的最好的。
答案 2 :(得分:1)
我选择了数据库端解决方案。假设一个包含列id
和value
的表,您应该创建一个包含所有“值”的列表,并使用以下SQL:
select count(*) from tbl where value in (:values);
将:values
参数绑定到值列表但是适合您的环境。 (当使用Spring JDBC和支持in
运算符的数据库时很简单,对于较小的设置,则较少。作为最后的手段,您可以动态生成SQL。)您将得到一个包含一行和一列的结果集。数字类型。如果为0,则可以插入新数据;如果为1,则报告违反约束。 (如果是其他任何问题,那么你会遇到一个全新的问题。)
如果您需要检查用户输入中的每个项目,请将查询更改为:
select value from tbl where value in (:values)
将结果存储在一个集合中(称为duplicates
),然后遍历用户输入项并检查当前项的值是否在duplicates
中。
这应该比将整个数据集整理到内存中更好。