Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带密钥提取器的二进制搜索Java列表_Java - Fatal编程技术网

带密钥提取器的二进制搜索Java列表

带密钥提取器的二进制搜索Java列表,java,Java,假设我有: class Item { int id; int type; } 我可以这样做: List<Item> items; Item itemToFind; Comparator<Item> itemComparator; Collections.binarySearch(items, itemToFind, itemComparator); 如果没有额外的开销(例如,将列表转换为列表以调用集合。binarySearch打开或类似)?比较器仍然是比较

假设我有:

class Item {
   int id;
   int type;
}
我可以这样做:

List<Item> items;
Item itemToFind;
Comparator<Item> itemComparator;
Collections.binarySearch(items, itemToFind, itemComparator);

如果没有额外的开销(例如,将
列表
转换为
列表
以调用
集合。binarySearch
打开或类似)?

比较器仍然是
比较器
。您要更改的是比较器的实现,以根据类型而不是id进行计算

Comparator<Item> comparator = new Comparator<Item>(){
    public int compare(Item a, Item b) 
    { 
        return a.getType() - b.getType(); 
    } 
}
在对这个问题进行思考后:

项目
用作打捆针的替代方法是将
比较器
建立在
项目
和打捆针机具的接口上

返回int值的接口:

 public interface Intgettable{
     public int getInt();
 }
必须实现此接口:

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<Intgettable> comparator = new Comparator<Intgettable>(){
        public int compare(Intgettable a, Intgettable b){
            return a.getInt() - b.getInt();
        }
};

您的问题是,在
集合中
java的二进制搜索实现只允许搜索
T
类型的项目。要搜索属于
T
的另一种类型,可以执行以下操作:

  • 将另一种类型包装在
    T
    中,在您的情况下,应如下所示:
  • 列表项;
    int-typeToFind;
    Item itemToFind=新项(/*id*/0的随机值,typeToFind);
    int index=binarySearch(items,itemToFind,(a,b)->a.getType()-b.getType());
    
    在此添加一些重要注释:

      -项目的比较应该只依赖于并且只依赖于'type',否则您可能会遇到一些讨厌的bug;
      -应该对项目列表进行排序。排序应仅取决于且仅取决于“type”(基本上使用与以前相同的比较器)
  • 从初始列表创建新列表:
  • 列表项;
    int-typeToFind
    int index=binarySearch(items.stream.map(item->item.getType()).collect(Collectors.toList()),itemToFind);
    

    据我所知,Java标准库没有提供二进制搜索实现,其中包含一个用于密钥相等的比较器。如果这些选项不能满足您的要求,您可能应该搜索库或实现自己的搜索。

    我不明白您为什么要提取类型。您可以编写一个仅比较类型的比较器。二进制搜索将返回您可以从中获取类型的项目。正如埃尔文所说,当您有一个项目列表时,您应该实现一个项目比较器,并将其用于二进制搜索search@ErvinSzilagyi这是
    binarySearch​(列表如果可能的话,你应该将你的
    typeToFind
    包装成一个
    。否则你应该创建一个新的数组。目前提出的解决方案只是需要类技巧的黑客,而我们真正需要的是一个
    binarySearch
    方法,该方法添加一个键提取器作为参数:
    binarySearch(ListYeah,Item像往常一样有一个
    getType
    getter。如果我没有
    Item
    ,但只有它的类型(如问题中的
    int-typeToFind
    ),我如何使用上述比较器调用
    Collections.binarySearch
    )当然可以,但实际上是这样的,这一行:
    Function typeExtractor=Item::getType;
    。但是,我不知道你建议我如何调用
    集合。binarySearch
    ,你能把它添加到你的答案中吗?我在前面的评论中放的那一行暗示
    Item
    有一个
    getType
    方法。我希望是假定getters和setters在Java中是一个标准的东西,并且被省略了。请假设它们在那里。您更新的答案不是答案-我有几次没有提到我没有
    Item Item tofind
    ,但是只有
    int typeToFind
    ?仍然需要一个项目,所以您创建了一个项目用作针并设置了它的类型。我添加了一个al用一种物品作为针。
    Intgettable typeTofind = ()->{return 6;};
    
    Comparator<Intgettable> comparator = new Comparator<Intgettable>(){
            public int compare(Intgettable a, Intgettable b){
                return a.getInt() - b.getInt();
            }
    };
    
    Collections.binarySearch(items, typeToFind, comparator );
    
    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);