我有两个Bill
个对象列表,其date
字段代表帐单创建的月份。我需要将bills
列表中的一些对象添加到oldBills
。如果oldBills
列表中没有相同数据的帐单,则应添加帐单。
我是这样实现的:
outer:
for (Bill bill : bills) {
Date billDate = bill.getDate();
for (Bill bill1 : oldBills) {
Date bill1Date = bill1.getDate();
if (Objects.equals(billDate, bill1Date)) {
continue outer;
}
}
newBills.add(bill);
}
oldBills.addAll(newBills);
但我认为这不是最佳方式。
您可能有任何想法,如何优化此算法?
p.s。:java 7
答案 0 :(得分:4)
由于Bill的getDate()必须是唯一的,我建议使用一个需要唯一密钥的Map,并且对密钥具有O(1)访问权限。
Map<Date, Bill> oldBills = new HashMap<>();
oldBills.putAll(newBills);
你也可以使用循环
for(Bill bill : newBills)
oldBills.putIfAbsent(bill.getDate(), bill);
这将取代所有具有相同Date
的账单。 putAll
通常是O(N)
操作,其中N是newBills
您可以从列表中构建这些地图。
// requires Java 8.
Map<Date, Bill> billByDate = bills.stream().collect(Collectors.groupingBy(Bill::getDate));
答案 1 :(得分:2)
如果比尔有&#39; n&#39;元素和oldBill有&#39; m,您的算法需要n * m
次迭代。它是O(n^2)
。可以通过对oldbill (O(n*logn) )
进行排序,然后对bill (O(logn))
的每个元素实施二进制搜索来改进它。因此,在这种情况下,所花费的总时间为O(nlog(n))
。
答案 2 :(得分:1)
for(Bill bill:bills)
{
if(!oldBills.contains(bill))
{
oldBills.add(bill);
}
}
我不确定你在做什么用'新账单',但是这会在没有重复记录的情况下向oldBills添加账单而不会强制执行并拥有^ 2算法。
答案 3 :(得分:1)
您可以使用HashMap对其进行优化。为此,您需要为Bill对象定义一个唯一的键。例如,日期和谁被支付到
count<<i->name; // for printing name.
答案 4 :(得分:0)
不是通过循环,而是使用返回布尔值的java.util.ArrayList.contains(Object o)。