说我有
class Item {
int id;
int type;
}
我可以这样做:
List<Item> items;
Item itemToFind;
Comparator<Item> itemComparator;
Collections.binarySearch(items, itemToFind, itemComparator);
但是,我只给出了对象的一个属性,而不是整个对象,例如上述示例中的type
。假设列表按该属性排序,那么Java或某些已建立的库中是否有标准方法可以实现此目的:
List<Item> items;
Function<Item, Integer> typeExtractor = Item::getType;
int typeToFind;
Comparator<Integer> typeComparator = Integer::compare;
binarySearch(items, typeExtractor, typeToFind, typeComparator);
没有额外的开销(例如,将List<Item>
转换为List<Integer>
以调用Collections.binarySearch
或类似的费用?
答案 0 :(得分:1)
比较器仍为Comparator<Item>
。您将要更改的是比较器的实现,以便根据类型而不是id进行评估。
Comparator<Item> comparator = new Comparator<Item>(){
public int compare(Item a, Item b)
{
return a.getType() - b.getType();
}
}
Item,需要将类型的吸气剂或属性设为公开。如果使用ID,则相同。
但是,不确定您如何建议我打电话 Collections.binarySearch
用法没有改变(改变的是比较器对象内部的比较方式):
Item itemToFind = new Item();
itemToFind.setType(typeToFind);
Collections.binarySearch(items, itemToFind, comparator );
对此主题进行了一些思考之后:
使用Item
作为针头的另一种方法是将Comparator
放在Item
和针头工具的接口上。
返回int值的接口:
public interface Intgettable{
public int getInt();
}
Item
应该必须实现此接口:
public class Item implements Intgettable{
private int id;
private int type;
public void setId(int id){
this.id = id;
}
public void setType(int type){
this.type = type;
}
public int getId(){
return id;
}
public int getType(){
return type;
}
public int getInt(){
return type;
}
}
要搜索的键是可以创建的Intgettable
:
1-使用扩展Intgettable
的类。
public static class MyItemKey implements Intgettable{
private int value;
public MyItemKey(int v){
this.value = v;
}
@Override
public int getInt(){
return value;
}
}
MyItemKey typeToFind = new MyItemKey(6);
2-作为方法内部的匿名类。
Intgettable typeTofind = new Intgettable(){
private int value = 6;
public int getInt(){
return value;
}
};
3-或使用lambda版本:
Intgettable typeTofind = ()->{return 6;};
Comparator
将是:
Comparator<Intgettable> comparator = new Comparator<Intgettable>(){
public int compare(Intgettable a, Intgettable b){
return a.getInt() - b.getInt();
}
};
最后在二进制搜索中使用它:
Collections.binarySearch(items, typeToFind, comparator );
答案 1 :(得分:0)
您的问题是,在Collection<T>
中,java的二进制搜索实现仅允许搜索T
类型的项目。为了搜索属于T
的另一种类型,您可以执行以下操作:
T
内,您的情况应如下所示:List<Item> items;
int typeToFind;
Item itemToFind = new Item(/* random value for id */ 0, typeToFind);
int index = binarySearch(items, itemToFind , (a, b) -> a.getType() - b.getType());
在此处添加一些重要说明:
List<Items> items;
int typeToFind
int index = binarySearch(items.stream.map(item -> item.getType()).collect(Collectors.toList()), itemToFind);
据我所知,Java的标准库不提供带有用于键相等性的比较器的二进制搜索实现。如果这些选项不能满足您的要求,则可能应该搜索库或实施自己的搜索。