2010-10-26 95 views
0

我有泛型结构,我需要使用各种泛型类型的属性进行搜索。替代泛型类型的字段

我们认为以下实现的:

public class Person { 
    private int id; 
    private String name; 
    // + getters & setters 
} 

现在我有我的自定义的数据结构和它的一个方法是这样的:

public T search(T data) { ... } 

这当然是无稽之谈。我真正需要的代码是一样的东西:

Person p = structure.search(12); // person's id 

Person p = structure.search("Chuck N."); // person's name 
在pseudoJava(:))

因此,代码会是这样的:

public T search(T.field key) 

这ISN”当然可能:(但是,如何处理这种情况?重点是:我不想强制客户端的类(如Person)实现我自己的接口或扩展我自己的类。是否有任何解决方法?

回答

2

看起来你想要某种中介的战略目标,即提取值,比较值,或许提供了一个哈希码或比较功能。

是这样的:

interface Matcher<T> { 
    boolean matches(T obj); 
} 

或方法,例如:

boolean matches(T obj, V value); 

    V get(T obj); 

    int hash(T obj); 

    int compare(T a, T b); 

使用是与当前Java语法稍微详细(可以针对JDK 8改变)。

你最终的东西是这样的:

Person p = structure.search(
    new Matcher<Person>() { public boolean matches(Person person) { 
     return person.getID() == 12; 
    }) 
); 

或:

Person p = structure.search(
    new Matcher<Person,Integer>() { 
     public boolean matches(Person person, Integer id) { 
      return person.getID() == id; 
     } 
    ), 
    12 
); 

在JDK8,或许是这样的:

Person p = structure.search(
    { Person person -> person.getID() == 12 } 
); 

或:

Person p = structure.search(
    { Person person, Integer id -> person.getID() == id }, 
    12 
); 

或:

Person p = structure.search(
    { Person person -> person.getID() }, 
    12 
); 

或:

Person p = structure.search(
    Person#getID, 12 
); 
+0

但Person类被强制执行Matcher,是否正确? – Xorty 2010-10-26 13:08:09

+0

不,我会再添加一些。 – 2010-10-26 13:16:51

+0

请这样做:) – Xorty 2010-10-26 13:22:02

2

您可以通过添加Class参数使搜索的签名包含类型参数。举个例子:

//replace 'id' with whatever your identifier types are 
public <T> T search(int id, Class<T> entityClass) { ... } 

客户将不得不使用的方法类似

Person p = foo.search(123, Person.class); 
NotAPerson n = foo.search(234, NotAPerson.class); 

它可能看起来有点丑必须包括类,但是当你真正想的事情 - 没有按”客户总是知道它在搜索什么?并且search()背后的代码不需要知道要搜索哪种类型 - 如果您具有由不同类型共享的ID,该怎么办?

如果你的ID是一致的类型的不是,你可以在签名更改为

public <T> T search(Serializable id, Class<T> entityClass) { ... } 
+0

我真的不知道,“id”是什么。它可能是int,string,date,无论如何:>我只知道它的T属性。这有帮助吗? :/ – Xorty 2010-10-26 12:45:41

+0

那么,你在寻找什么 - T的“标识符”,或T的任何任意属性?这个例子其实并不重要,第一个参数可以用'search()'方法解释为任何东西 - 我的答案的实际部分是添加'Class '作为参数。 – 2010-10-26 12:47:05

+0

你是否介意编辑你的答案,例如我写的?我不太明白你的观点。我有同质结构。我知道,这种结构中只有Ts。在我们的例子中 - 我有充满人的结构。没有别的东西到达那里我不知道的是我应该在我的搜索方法中指定什么“关键”。换句话说,你会用什么来代替你的“int id”?你如何访问T的领域? – Xorty 2010-10-26 12:56:48

0

我建议你使用可比接口。

Person p = structure.searchUnique(new FieldFilter(“id”,12)); Person搜索id为12 Person [] p = structure.searchAll(new FieldFilter(“name”,“John”)); //搜索名为John

而且我们可以实现过滤器,可以搜索超过目标类的所有可用字段人:

人[P = structure.searchAll(新FieldFilter(“约翰”)) ; //搜索所有Johns

如何实施?这里有一些提示。

首先什么是“结构”?它是一个包含收集的封装,将来可能包含一些索引功能。这个类应该像

构造函数结构(集合数据);

其在给定集合搜索方法进行迭代,并调用compateTo()FieldFilter的方法实现可比:对(T ELEM:集合)

{ 如果(filter.compareTo(ELEM)){ result.add (ELEM); } } 返回结果;

的FieldFilter应该是这样的:

公共类FieldFilter实现可比{ 私人字符串字段名; private V fieldValue; public FieldFilter(String fieldName,V fieldValue){ this.fieldName = fieldName; this.fieldValue = fieldValue; } public boolean compareTo(T elem){field} = elem.getClass()。getField(fieldName); field.setAccessible(true); return field.getValue()。equals(fieldValue); } }

请注意,代码是直接以答案形式编写的,从未编译过,因此无法按原样使用。但我希望它能描述这个想法。

+0

我也在考虑使用反射,但我认为这不是最优的。由于程序员 - 作为API客户端 - 不太了解java.lang.reflect,它也带来了潜在的问题(我们都知道它是哪个)。 – Xorty 2010-10-26 13:47:46

0

如果要通过搜索类型和传递给search()方法的参数类型之间的泛型实施映射,必须在某处指定此地址。如果没有至少一个客户端类的通用标记接口,我认为没有办法做到这一点。

像这样的事情,例如将工作:

public interface Searchable<T> { } 

public class Person implements Searchable<String> { 
    // ... 
} 

public <T extends Searchable<K>, K> T search(K key) { 
    // ... 
} 

所以,现在的编译器将允许:

Person p = search("John Doe"); 

但不是:

Person p = search(5); 

如果连一个标记接口不一个选项,恐怕最好的选择是使用基于参数类型的特定搜索方法,如:

public <T> T searchByInt(int key) { 
    // ... 
} 

public <T> T searchByString(String key) { 
    // ... 
} 

但当然,这将意味着无效的情况下,像

Person p = searchByInt(5); 

不会在编译时被捕获,而是需要在运行时检查来代替。

+0

yayx,这是好的和可读的,但我不能现在重新实现原始类:)我感谢您的建议,但匹配模式(汤姆霍金写道)现在更适合我。 – Xorty 2010-10-26 13:43:26

+0

好的;我以为你正在寻找一个像搜索(K)这样的方法签名,K以某种方式映射到Person类。但是,如果传递匿名接口实现以及一些匹配逻辑也可以,那么是的,我同意汤姆霍金的解决方案可能是最适合你的解决方案。 – 2010-10-26 14:13:25