我无法确定哪个 Java 集合最适合我的场景。目前,我正在阅读一条记录,该记录为我提供了“帐号”和“客户名称”值。
基于这些值,我需要根据第一个文件中提供的帐号和客户名称搜索另一个文件。问题是第二个文件中的帐号不是唯一的,所以我需要同时使用帐号和客户名称进行搜索。
我不想为我从第一个文件中读取的每条记录打开、读取、搜索、关闭第二个文件,而是想将整个文件读入一个集合并使用 Collections 二进制搜索来定位第二个文件中的关联记录。
是否有某种类型的收藏最适合这个目的(如果有的话)?
我无法确定哪个 Java 集合最适合我的场景。目前,我正在阅读一条记录,该记录为我提供了“帐号”和“客户名称”值。
基于这些值,我需要根据第一个文件中提供的帐号和客户名称搜索另一个文件。问题是第二个文件中的帐号不是唯一的,所以我需要同时使用帐号和客户名称进行搜索。
我不想为我从第一个文件中读取的每条记录打开、读取、搜索、关闭第二个文件,而是想将整个文件读入一个集合并使用 Collections 二进制搜索来定位第二个文件中的关联记录。
是否有某种类型的收藏最适合这个目的(如果有的话)?
假设您有足够的内存,我可能会使用HashMap<AccountIdentifier, CustomerRecord>
.
WhereCustomerRecord
是一个包含您要查找的记录的对象。
然后创建一个关键类:
public class AccountIdentifier {
public String accountNumber;
public String customerName;
public AccountIdentifier(String accountNumber, String customerName) {
this.accountNumber = accountNumber;
this.customerName = customerName;
}
public int hashCode() {
return (accountNumber+"#"+customerName).hashCode();
}
public boolean equals(Object obj) {
if(!(obj instanceof AccountIdentifier)) return false;
else {
AccountIdentifier id = (AccountIdentifier)obj;
return accountNumber.equals(id.accountNumber) && customerName.equals(id.customerName);
}
}
}
因此,您必须通过读取每条记录并CustomerRecord
使用其中包含的数据创建一个实例来将第二个文件预加载到内存中,并且还要AccountIdentifier
放入您的Map
:
theMap.put(accountIdentifier, customerRecord);
到了要搜索的时候,您已经从第一个文件中获得了 accountNumber 和 customerName,然后执行以下操作:
AccountIdentifier accountIdentifier = new AccountIdentifier(accountNumber, customerName);
CustomerRecord record = theMap.get(accountIdentifier);
最后的评论,如果您的文件太大而无法放入内存,那么您应该考虑使用像ehcache这样的缓存库。
最好的办法是创建一个包含帐号和客户名称的对象。然后您可以将您的客户文件读入到 a 中Map<CustomerInfo, FileInfo>
。在这里,CustomerInfo
是您的对象,其中仅包含客户姓名和帐号,并且FileInfo
是您的对象,其中包含从文件中读取的所有信息。现在您可以对地图进行简单的查找。
请注意,您需要确保CustomerInfo
实现hashCode()
并equals()
使其正常工作。
我认为这更多地取决于您如何定义您的记录,而不是实际收藏。
您可以创建一个Comparator
比较两条记录的记录,并且基本上考虑了 id 和 name,如果它们匹配,则假设它是相同的记录。
基于此,您可以使用您定义的比较器来搜索ArrayList
(例如)符合您条件的记录。
二进制搜索仅在您仅返回一个匹配项时才有用,正如您从方法签名中看到的那样,并且您需要Collection
在调用二进制搜索之前对其进行排序。
所以,总结一下:
定义一个Comparator
接受两个Record
对象并检查它们是否具有相同 id/name 的 a。
例如,将所有记录加载到一个ArrayList
中。
对它们进行排序。
Collections.binarySearch
使用您的排序集合和自定义比较器调用。
为什么不做得更快呢?
创建一个类客户:
public class Customer {
private final int accountNumber;
private final String customerName;
public Customer (int accountNumber, String customerName) {
this.accountNumber = accountNumber;
this.customerName = customerName;
}
public boolean equals(Object o) {
//check if accountNumber and customerName are equal
}
public int hashCode() {
return 13*accountNumber + 31*customerName.hashCode();
}
}
public class CustomerBucket() {
private final int forAccountNumber;
private Map<String, Customer> map = HashMap<String, Customer>();
public CustomerBucket(int forAccountNumber) {
//...
}
public boolean equals(Object o) {
return o.forAccountNumber == this.forAccountNumber;
}
public int hashCode() {
return forAccountNumber;
}
}
public class AccountSearcher {
private final Set<CustomerBucket> set = new HashSet<CustomerBucket>();
public Customer getCustomer(int accountNumber, String name) {
return set.get(accountNumber).get(name);
}
}
这样,您几乎可以在 O(1) 中搜索记录。此方法还使您能够搜索 accountNumbers(并返回与该号码关联的名称列表)。