我有一个分支类,它有一个客户对象的arraylist。在分支类中,我希望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对象,我在对象中寻找一个值。任何建议将不胜感激。
编辑:谢谢大家,这些答案太棒了。
通常,您不能只是循环遍历列表来查找值。
在代码重复方面,将customerExists
的主体替换为:
return customerPosition() >= 0;
并且,在addTransaction()
中,将customerPosition()
的结果存储在变量中,并使用thatVariable >= 0
而不是调用customerExists()
。
如果您使用的是Java 8+,则可以使用流:
Optional<Customer> cust = customers.stream().filter(c -> c.getCustomerName().equals(customerName)).findFirst();
然后你根本不用担心使用索引。
而不是使用Multiple for循环,使用单个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;
}
在您的方法中使用Customer
public void addTransaction(String customerName, Double transactionValue) {
Customer customer = getCustomerUsingName(customerName)
if(customer == null) {
return;
}
customer.addTransaction(transactionValue);
}
即使您可以使用'indexOf'的某些突变变体,也不会提高效率。要在未排序的数组中查找数据,您必须遍历数组以查找它。这是选择存储数据的数组所固有的。
但是你为什么要使用customerExists呢? customerPosition执行完全相同的逻辑。你只需要调用一次。
int pos = customerPosition(...);
if (pos >= 0)
customers.get(pos).addTransaction(...);
else
... does not exist ...
使用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);
}
}
您可以改用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
同意Andy Turner的第一个答案。在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.
}
}
技术说明
Stream有forEach和peek方法。如果您需要将您的使用者应用于流的所有元素,并且仍然有一个新流(一个惰性操作) - 请使用peek
。如果要为所有元素应用消费者并终止流(不再需要流) - 请使用终端操作 - forEach
。