我有一个分支类,其中包含客户对象的数组列表。在分支类中,我要addTransaction
输入给定的客户名称,但首先要检查客户是否存在,然后添加交易。
private boolean customerExists(String customerName) {
for (int i = 0; i < customers.size(); i++) {
if(customers.get(i).getCustomerName().equalsIgnoreCase(customerName)) {
return true;
}
}
return false;
}
private int customerPosition(String customerName) {
for (int i = 0; i < customers.size(); i++) {
if(customers.get(i).getCustomerName().equalsIgnoreCase(customerName)) {
return i;
}
}
return -1;
}
public void addTransaction(String customerName, Double transactionValue) {
if(customerExists(customerName) == false) {
System.out.println("Customer with name " + customerName + " not found");
} else {
customers.get(customerPosition(customerName)).addTransaction(transactionValue);
}
}
我知道这段代码将起作用,但是我很清楚自己必须对arraylist进行2次循环以检查其存在并获得其位置。效率低下
我知道indexOf
方法将在addTransaction
中有用,但是我不确定如果要在对象内部而不是对象本身中查找特定值,该如何使用它。我不是在寻找Customer对象,而是在对象内寻找值。任何建议将不胜感激。
编辑:谢谢大家,这些答案很棒。
答案 0 :(得分:3)
通常,除了遍历列表以查找值之外,您不能做得更好。
就代码重复而言,将customerExists
的主体替换为:
return customerPosition() >= 0;
然后,在addTransaction()
中,将customerPosition()
的结果存储在变量中,并使用thatVariable >= 0
而不是调用customerExists()
。
如果您使用的是Java 8+,则可以使用流:
Optional<Customer> cust = customers.stream().filter(c -> c.getCustomerName().equals(customerName)).findFirst();
那么您完全不必担心使用索引。
答案 1 :(得分:1)
而不是使用Multiple for循环,而是使用single for循环并获取客户对象并使用它,
private Customer getCustomerUsingName(String customerName) {
for (int i = 0; i < customers.size(); i++) {
if(customers.get(i).getCustomerName().equalsIgnoreCase(customerName)) {
return customers.get(i);
}
}
return null;
}
以您的方式使用客户
public void addTransaction(String customerName, Double transactionValue) {
Customer customer = getCustomerUsingName(customerName)
if(customer == null) {
return;
}
customer.addTransaction(transactionValue);
}
答案 2 :(得分:0)
即使您可以使用'indexOf'的某些变体,也不会提高效率。要在未排序的数组中查找数据,您必须遍历数组以寻找数据。这是选择存储数据的数组所固有的。
但是您为什么要完全使用customerExists? customerPosition执行完全相同的逻辑。您只需调用一次即可。
int pos = customerPosition(...);
if (pos >= 0)
customers.get(pos).addTransaction(...);
else
... does not exist ...
答案 3 :(得分:0)
使用customerPosition
方法检查是否存在Customer
public void addTransaction(String customerName, Double transactionValue) {
final int index = customerPosition(customerName);
if(index == -1) {
System.out.println("Customer with name " + customerName + " not found");
} else {
customers.get(index).addTransaction(transactionValue);
}
}
答案 4 :(得分:0)
您可以改用HashMap,
通常,在某些情况下,ArrayList比HashTable快,但是当您必须查找元素时,HashTable(使用键进行搜索)比ArrayList快,您可以使用它:
HashMap<String, Customer> myCustomers = new HashMap<String, Customer>();
myCustomers.put("NameID_1", customerObject_1);
myCustomers.put("NameID_2", customerObject_2);
myCustomers.put("NameID_3", customerObject_3);
myCustomers.put("NameID_4", customerObject_4);
System.out.println(myCustomers.get("NameID_1"));
// just check if the customer exists in your Map
答案 5 :(得分:0)
同意安迪·特纳的第一个答案。在findFirst()
之后,您可以应用ifPresent
使用方,它将添加交易。
customers.stream()
.filter(c -> c.getCustomerName().equals(customerName))
.findFirst()
.ifPresent(customer -> customer.addTransaction(transactionValue));
如果将来您需要向与过滤谓词匹配的所有客户添加交易,则可以使用forEach
并传递上一个示例中的使用方。
customers.stream()
.filter(c -> c.getCustomerName().equals(customerName))
.forEach(customer -> customer.addTransaction(transactionValue));
如果您使用Java版本的波纹管8,则循环可能会稍有改善。您可以有一个循环
Iterator it = customers.iterator();
while (it.hasNext()) {
Customer customer = it.next();
if (customerPredicate.test(customer)) { // your if condition
customer.addTransaction(transactionValue); // your consumer.
break; // If you need to change only first customer.
}
}
技术说明
流具有 forEach 和 peek 方法。如果您需要将使用者应用于流的所有元素,并且仍然有新的流(惰性操作),请使用peek
。如果要对所有元素应用使用者并终止流(不再需要流),请使用终端操作-forEach
。