private void fillInvoiceListForName(String name, ArrayList<Invoice> mInvoices) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
mInvoices.addAll(contract.getInvoices());
}
}
}
}
private void fillIncomeListForName(String name, ArrayList<Income> mIncomes) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
mIncomes.addAll(contract.getIncomes());
}
}
}
}
private void fillDocumentListForName(String name, ArrayList<Document> mDocuments) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
mDocuments.addAll(contract.getDocuments());
}
}
}
}
答案 0 :(得分:4)
您的所有方法都有共同的迭代。您要做的是抽象迭代方法,同时允许调用者指定要对正在迭代的对象执行的操作。基本上,您希望将内部迭代器(执行迭代)与策略(执行操作)结合起来。
使用策略模式,您可以定义所有具有共同点的不同策略,然后轻松地将其替换为另一个策略。在这种情况下,您的所有方法都会从合同列表中收集信息并将其添加到列表中,但它们收集的信息会有所不同。
private <E> void fillListForName(String name, List<? super E> listToFill, FillStrategy<E> fillStrategy) {
if (name == null) {
throw new IllegalArgumentException("name cannot be null");
}
for (SupplierAccount account : listContracts) {
if (name.equals(account.getSupplier())) {
List<Contract> contracts = account.getContracts();
for (Contract contract : contracts) {
fillStrategy.execute(listToFill, contract);
}
}
}
}
FillStrategy
接口和示例实现interface FillStrategy<T> {
public void execute(List<? super T> listToFill, Contract contract);
}
class InvoiceFillStrategy implements FillStrategy<Invoice> {
@Override
public void execute(List<? super Invoice> listToFill, Contract contract) {
listToFill.addAll(contract.getInvoices());
}
}
List<Invoice> invoices = new ArrayList<Invoice>();
InvoiceFillStrategy invoiceStrategy = new InvoiceFillStrategy();
System.out.println("Invoices for myCorp:");
fillListForName("myCorp", invoices, invoiceStrategy);
for (Invoice i : invoices) {
System.out.println(i);
}
System.out.println("\nInvoices for otherCorp:");
invoices.clear();
fillListForName("otherCorp", invoices, invoiceStrategy);
for (Invoice i : invoices) {
System.out.println(i);
}
这种方法的好处是您可以创建其他“策略”,而无需修改任何其他涉及的类。例如,您可以创建一个收集超过给定阈值的所有发票的发票:
class ExpensiveInvoiceFillStrategy implements FillStrategy<Invoice> {
private int minimumAmount;
public ExpensiveInvoiceFillStrategy(int minimumAmount) {
this.minimumAmount = minimumAmount;
}
@Override
public void execute(List<? super Invoice> listToFill, Contract contract) {
for (Invoice invoice : contract.getInvoices()) {
if (invoice.getAmount() >= minimumAmount) {
listToFill.add(invoice);
}
}
}
}
只是实现此类,然后使用它的实例调用fillListForName
就足够了 - 不需要更改fillListForName
或Contract
!
还有其他方法可以实现迭代器方法和策略 - 有些甚至可以被认为是“更纯粹”或“更好”,就像我在这里所做的那样。我之所以选择这种方法,是因为它保持代码与您的代码类似,并且因为我们正在尝试解决特定问题,而不是在Java中实现对内部迭代器的一般支持(更聪明的人已经在研究它)。请注意,它并非“完美”:)
答案 1 :(得分:1)
考虑使用Guava,它具有强大的实用程序来操作集合。例如,您可以将FluentIterable
与Predicate
和Function
结合使用,以提取常用逻辑,并使用它们来转换和过滤您的集合。
下面我已经将常见元素提取到filterAndTransform
方法中,该方法允许您传入Function
,以便您可以从Contract
对象中收集您喜欢的内容:
private <T> List<T> filterAndTransform(String name, Function<Contract, Iterable<T>> function) {
return FluentIterable.from(listcontracts)
.filter(new HasSupplierPredicate())
.filter(new SupplierNameMatchesPredicate(name))
.transformAndConcat(new Function<SupplierAccount, Iterable<Contract>>() {
@Override public Iterable<Contract> apply(final SupplierAccount account) {
return account.getContracts();
}
})
.transformAndConcat(function)
.toList();
}
private void fillInvoiceListForName(String name, ArrayList<Invoice> mInvoices) {
final Iterable<Invoice> invoices = filter(name,
new Function<Contract, Iterable<Invoice>>() {
@Override public Iterable<Invoice> apply(final Contract contract) {
return contract.getInvoices();
}
});
mInvoices.addAll(invoices);
}
private void fillIncomeListForName(String name, ArrayList<Income> mIncomes) {
final Iterable<Income> incomes = filter(name,
new Function<Contract, Iterable<Income>>() {
@Override public Iterable<Income> apply(final Contract contract) {
return contract.getIncomes();
}
});
mIncomes.addAll(incomes);
}
// etc...
答案 2 :(得分:0)
定义枚举,并将其作为参数传递给方法:
public enum ContractValue {
INVOICE, INCOME, DOCUMENT;
}
private void fillIncomeListForName(String name, ArrayList<Income> mIncomes, ContractValue contractValue) {
for (SupplierAccount account : listcontracts) {
if (account.getSupplier() != null)
if (account.getSupplier().equals(name)) {
ArrayList<Contract> mContracts = account.getContracts();
for (Contract contract : mContracts) {
if (contractValue == ContractValue.INCOME) {
mIncomes.addAll(contract.getIncomes());
} else if (contractValue == ContractValue.INVOICE) {
mInvoices.addAll(contract.getInvoices());
} else if (contractValue == ContractValue.DOCUMENT) {
mDocuments.addAll(contract.getDocuments());
}
}
}
}
}