問題
我正在嘗試設計兩種過濾串列的方法
public List<TypeA> filter(List<TypeA> typeAList) {
//duplicated code
//filter typeAList using some parameters in typeA objects
//return filtered list
}
public List<TypeB> filter(List<TypeB> typeBList) {
//duplicated code
//filter typeBList using some parameters in typeB objects
//return filtered list
}
問題是這兩種方法都有重復的代碼,除了過濾部分,我在 TypeA 和 TypeB 中訪問不同的引數。
到目前為止我嘗試過的事情
- 我嘗試制作這樣的通用方法。但這不支持 TypeA 和 TypeB 以外的型別。鼓勵某人使用非預期型別呼叫此方法。
public <T> List<T> filter(List<T> genericList) {
//duplicated code
if (T instanceOf TypeA)
//filtering code for TypeA
if (T instanceOf TypeB)
//filtering code for TypeB
//return filtered list
}
- 使用兩個呼叫私有通用過濾器方法的方法多載。我覺得這確保了對公共方法的意外呼叫,同時仍然使用泛型來避免代碼重復。
public List<TypeA> filter(List<TypeA> typeAList) {
//call innerFilter(typeAList)
}
public List<TypeB> filter(List<TypeB> typeBList) {
//call innerFilter(typeBList)
}
private <T> List<T> innerFilter(List<T> genericList) {
//duplicated code
if (T instanceOf TypeA)
//filtering code for TypeA
if (T instanceOf TypeB)
//filtering code for TypeB
//return filtered list
}
- 試圖使這兩個類實作一個通用介面并將該介面用作我的方法的輸入引數。但是其中一類是第三方的,不受我控制。
需要幫助
我真的是設計新手。想了解我的推理是否正確。還尋找有關解決此問題的替代最佳方法的建議。提前致謝。
uj5u.com熱心網友回復:
這正是Predicate<T>
函式式介面旨在解決的問題型別。
import java.util.List;
import java.util.function.Predicate;
public class SOQ_20220501
{
public static void main(String[] args)
{
record TypeA(int a) {}
record TypeB(boolean b) {}
final List<TypeA> as = List.of(new TypeA(0), new TypeA(1), new TypeA(2), new TypeA(3), new TypeA(4));
final List<TypeB> bs = List.of(new TypeB(true), new TypeB(false));
var whateverA = filter(as, typeA -> typeA.a() % 2 == 1);
System.out.println(whateverA);
var whateverB = filter(bs, typeB -> typeB.b());
System.out.println(whateverB);
}
public static <T> List<T> filter(List<T> typeAList, Predicate<T> predicate)
{
return
typeAList.stream()
.filter(predicate)
.toList()
;
}
}
uj5u.com熱心網友回復:
適當的結構不是反射的,并且不使用instanceof
.
public List<TypeA> filter(List<TypeA> typeAList) {
innerFilter(typeAList, typeA -> isGoodA(typeA))
}
private boolean isGoodA(TypeA a) { ... }
public List<TypeB> filter(List<TypeB> typeBList) {
innerFilter(typeBList, typeB -> isGoodB(typeB))
}
private boolean isGoodB(TypeB a) { ... }
private <T> List<T> innerFilter(List<T> genericList, Predicate<T> pred) {
//duplicated code
//filter genericList using pred
//return filtered list
}
uj5u.com熱心網友回復:
假設您有這 2 個TypeX
介面,沒有繼承鏈接并且具有相同的方法簽名。
interface TypeA {
String methodFromA();
}
interface TypeB {
String methodFromB();
}
您可以宣告一個 Enum,它知道必須為每個 TypeX 介面呼叫哪個方法。
enum FilterType {
TYPE_A(TypeA.class){
@Override
public <T> void callMethod(T typeX) {
TypeA typeA = (TypeA) typeX;
typeA.methodFromA();
}
},
TYPE_B(TypeB.class){
@Override
public <T> void callMethod(T typeX) {
TypeB typeB = (TypeB) typeX;
typeB.methodFromB();
}
};
Class typeClass;
FilterType(Class typeClass) {
this.typeClass = typeClass;
}
public static FilterType from(Class<?> typeClass) {
return Arrays.stream(values())
.filter(filterType -> filterType.typeClass.equals(typeClass))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("FilterType for class '" typeClass "' not exist")),
}
public abstract <T> void callMethod(T typeX);
}
最后,在您的過濾器方法中,您只需使用 TypeX 類恢復列舉實體并在其上呼叫適當的方法。
class FilterService<T> {
// The class type of TypeX interface
private final Class<T> typeClass;
public FilterService() {
// Recover the class of the generic T
this.typeClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
public List<T> filter(List<T> genericList) {
FilterType filterType = FilterType.from(typeClass); // Will throw IllegalArgumentException if T class isn't handle
genericList.forEach(typeX -> filterType.callMethod(typeX));
//return filtered list
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/470412.html
上一篇:使用通用函式復制不重復