Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.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_Binary Search_Comparator - Fatal编程技术网

Java 为二进制搜索的复合对象编写比较器

Java 为二进制搜索的复合对象编写比较器,java,binary-search,comparator,Java,Binary Search,Comparator,我有一个类和实例列表,看起来像这样(更改字段名以保护无辜/专有): 公共类膨胀 { 公共长时间(毫秒); 公共长空格单位; 公共长期成本; } 公共类膨胀生产者 { 最终私有列表bloatList=new ArrayList(); 最终私有随机=新随机(); 公共无效生产商人数() { int n=bloatList.size(); Bloat previousBloat=(n==0)?new Bloat():bloatList.get(n-1); Bloat newBloat=新的Bloat(

我有一个类和实例列表,看起来像这样(更改字段名以保护无辜/专有):

公共类膨胀
{
公共长时间(毫秒);
公共长空格单位;
公共长期成本;
}
公共类膨胀生产者
{
最终私有列表bloatList=new ArrayList();
最终私有随机=新随机();
公共无效生产商人数()
{
int n=bloatList.size();
Bloat previousBloat=(n==0)?new Bloat():bloatList.get(n-1);
Bloat newBloat=新的Bloat();
newBloat.timeinmillizes=
previousBloat.timeinmillides+random.nextInt(10)+1;
newBloat.spaceInBytes=
previousBloat.spaceInBytes+random.nextInt(10)+1;
newBloat.costInPennies=
上一个bloat.costInPennies+random.nextInt(10)+1;
bloatList.add(newBloat);
}
/*其他领域/方法*/
公共布尔测试单调性()
{
Bloat-previousBloat=null;
for(Bloat thisBloat:bloatList)
{
如果(上一次膨胀!=null)
{
如果((previousBloat.Timein毫秒)
>=thisblot.timein毫秒)
||(以前的bloat.spaceInBytes
>=thisBloat.spaceInBytes)
||(先前的膨胀
>=此膨胀。成本(单位:便士)
返回false;
}
previousBloat=此Bloat;
}
返回true;
}
膨胀生产者膨胀生产者;
列表
bloatList
BloatProducer
在内部保存,并以这样的方式进行维护:它只附加新的
Bloat
记录,不修改任何旧记录,并且每个字段都是单调递增的,例如
BloatProducer.testmonotonity()
将始终返回
true

我想使用
Collections.binarySearch(list,key,comparator)
来搜索
Bloat
记录,搜索方式可以是timein毫秒、spaceInBytes或costInPennies字段。(如果数字介于两条记录之间,我想查找上一条记录)


编写一系列3个Comparator类的最简单方法是什么?我是否必须使用一个膨胀对象的键,并为我没有搜索的对象使用虚拟字段?

如果你想利用对所有三个属性的二进制搜索,你必须为它们创建Comparator,并对其他列表或树集进行排序y比较器。

如果要按3个属性中的每一个进行搜索,则需要有3个独立的
比较器

一个更简洁的选择是使用一个通用的
比较器
,它接收一个参数,告诉它通过哪个字段进行比较

基本的通用比较器应该如下所示:

public class BloatComparator implements Comparator<Bloat>
{
    CompareByEnum field;

    public BloatComparator(CompareByEnum field) {
        this.field = field;
    }

    @Override
    public int compare(Bloat arg0, Bloat arg1) {
        if (this.field == CompareByEnum.TIME){
            // compare by field time
        }
        else if (this.field == CompareByEnum.SPACE) {
            // compare by field space
        }
        else {
            // compare by field cost
        }
    }
}
公共类BloatComparator实现Comparator
{
CompareByEnum字段;
公共BloatComparator(CompareByEnum字段){
this.field=字段;
}
@凌驾
公共整数比较(膨胀arg0,膨胀arg1){
if(this.field==CompareByEnum.TIME){
//按现场时间比较
}
else if(this.field==CompareByEnum.SPACE){
//按字段空间比较
}
否则{
//按现场成本进行比较
}
}
}

您需要为要比较的每个字段编写一个单独的比较器:

public class BloatTimeComparator implements Comparator<Bloat> {
    public int compare(Bloat bloat1, Bloat bloat2) {
        if (bloat1.timeInMilliseconds > bloat2.timeInMilliseconds) {
            return 1;
        } else if (bloat1.timeInMilliseconds < bloat2.timeInMilliseconds) {
            return -1;
        } else {
            return 0;
        }
    }
}
对于binarySearch方法,返回值为:

搜索键的索引(如果它包含在列表中);否则,((插入点)-1)。插入点定义为将键插入列表的点:大于键的第一个元素的索引,或list.size()如果列表中的所有元素都小于指定的键。请注意,这保证了当且仅当找到键时,返回值将>=0


这是您指定的所需索引。

以下是编写第一个比较器的测试驱动方法:

public class BloatTest extends TestCase{
    public class Bloat {
        public long timeInMilliseconds;
        public long spaceInBytes;
        public long costInPennies;

        public Bloat(long timeInMilliseconds, long spaceInBytes, long costInPennies) {
            this.timeInMilliseconds = timeInMilliseconds;
            this.spaceInBytes = spaceInBytes;
            this.costInPennies = costInPennies;
        }
    }

    public void testMillisecondComparator() throws Exception {
        Bloat a = new Bloat(5, 10, 10);
        Bloat b = new Bloat(3, 12, 12);
        Bloat c = new Bloat(5, 12, 12);

        Comparator<Bloat> comparator = new MillisecondComparator();
        assertTrue(comparator.compare(a, b) > 0);
        assertTrue(comparator.compare(b, a) < 0);
        assertEquals(0, comparator.compare(a, c));
    }

    private static class MillisecondComparator implements Comparator<Bloat> {
        public int compare(Bloat a, Bloat b) {
            Long aTime = a.timeInMilliseconds;
            return aTime.compareTo(b.timeInMilliseconds);
        }
    }


}
public类bloassert扩展了TestCase{
公共类膨胀{
公共长时间(毫秒);
公共长空格单位;
公共长期成本;
公共膨胀(长时间毫秒、长空间字节、长成本字节){
this.timeinmillizes=timeinmillizes;
this.spaceInBytes=spaceInBytes;
this.costInPennies=costInPennies;
}
}
public void testmillissecondcomparator()引发异常{
膨胀a=新膨胀(5,10,10);
膨胀b=新膨胀(3,12,12);
Bloat c=新的Bloat(5,12,12);
比较器比较器=新的毫秒比较器();
assertTrue(比较器比较(a,b)>0);
assertTrue(比较器比较(b,a)<0);
assertEquals(0,比较器。比较(a,c));
}
私有静态类毫秒比较器实现比较器{
公共整数比较(膨胀a、膨胀b){
长时间=a.timein毫秒;
返回aTime.compareTo(b.timein毫秒);
}
}
}
测试程序(
MultiBinarySearch.java
)以查看这些想法是否正常工作(它们似乎:

package com.example.test;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.List;
导入java.util.Random;
阶级膨胀
{
最终公共长时间(毫秒);
最终公共长空格单位;
最终公共长期成本;
静态最终私有整数N=100;
公共膨胀(长l1、长l2、长l3){
timeinms=l1;
spaceInBytes=l2;
成本指数=l3;
}
公共Bloat(){this(0,0,0);}
公共膨胀更多膨胀(随机r)
{
还新
Collections.binarySearch(bloatList,  bloatObjectToFind, 
    new BloatTimeComparator());
public class BloatTest extends TestCase{
    public class Bloat {
        public long timeInMilliseconds;
        public long spaceInBytes;
        public long costInPennies;

        public Bloat(long timeInMilliseconds, long spaceInBytes, long costInPennies) {
            this.timeInMilliseconds = timeInMilliseconds;
            this.spaceInBytes = spaceInBytes;
            this.costInPennies = costInPennies;
        }
    }

    public void testMillisecondComparator() throws Exception {
        Bloat a = new Bloat(5, 10, 10);
        Bloat b = new Bloat(3, 12, 12);
        Bloat c = new Bloat(5, 12, 12);

        Comparator<Bloat> comparator = new MillisecondComparator();
        assertTrue(comparator.compare(a, b) > 0);
        assertTrue(comparator.compare(b, a) < 0);
        assertEquals(0, comparator.compare(a, c));
    }

    private static class MillisecondComparator implements Comparator<Bloat> {
        public int compare(Bloat a, Bloat b) {
            Long aTime = a.timeInMilliseconds;
            return aTime.compareTo(b.timeInMilliseconds);
        }
    }


}
package com.example.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

class Bloat
{
    final public long timeInMilliseconds;
    final public long spaceInBytes;
    final public long costInPennies;
    static final private int N = 100; 
    public Bloat(long l1, long l2, long l3) {
        timeInMilliseconds = l1;
        spaceInBytes = l2;
        costInPennies = l3; 
    }
    public Bloat() { this(0,0,0); }
    public Bloat moreBloat(Random r)
    {
        return new Bloat(
                timeInMilliseconds + r.nextInt(N) + 1,
                spaceInBytes + r.nextInt(N) + 1,
                costInPennies + r.nextInt(N) + 1
        );
    }
    public String toString() {
        return "[bloat: time="+timeInMilliseconds
            +", space="+spaceInBytes
            +", cost="+costInPennies
            +"]";
    }

    static int compareLong(long l1, long l2)
    {
        if (l2 > l1)
            return -1;
        else if (l1 > l2)
            return 1;
        else
            return 0;
    }

    public static class TimeComparator implements Comparator<Bloat> {
        public int compare(Bloat bloat1, Bloat bloat2) {
            return compareLong(bloat1.timeInMilliseconds, bloat2.timeInMilliseconds);
        }
    }
    public static class SpaceComparator implements Comparator<Bloat> {
        public int compare(Bloat bloat1, Bloat bloat2) {
            return compareLong(bloat1.spaceInBytes, bloat2.spaceInBytes);
        }
    }
    public static class CostComparator implements Comparator<Bloat> {
        public int compare(Bloat bloat1, Bloat bloat2) {
            return compareLong(bloat1.costInPennies, bloat2.costInPennies);
        }
    }
    enum Type { 
        TIME(new TimeComparator()), 
        SPACE(new SpaceComparator()),
        COST(new CostComparator());

        public Comparator<Bloat> comparator;
        Type(Comparator<Bloat> c) { this.comparator = c; } 
    } 
}

class BloatProducer
{
    final private List<Bloat> bloatList = new ArrayList<Bloat>();
    final private Random random = new Random();
    public void produceMoreBloat()
    {
        int n = bloatList.size();
        Bloat newBloat = 
            (n == 0) ? new Bloat() : bloatList.get(n-1).moreBloat(random);
            bloatList.add(newBloat);
    }
    /* other fields/methods */

    public boolean testMonotonicity()
    {
        Bloat previousBloat = null;
        for (Bloat thisBloat : bloatList)
        {
            if (previousBloat != null)
            {
                if ((previousBloat.timeInMilliseconds 
                        >= thisBloat.timeInMilliseconds)
                    || (previousBloat.spaceInBytes 
                        >= thisBloat.spaceInBytes)
                    || (previousBloat.costInPennies
                        >= thisBloat.costInPennies))
                    return false;
            }
            previousBloat = thisBloat;
        }
        return true;
    }
    public int searchBy(Bloat.Type t, Bloat key)
    {
        return Collections.binarySearch(bloatList, key, t.comparator);
    }
    public void showSearch(Bloat.Type t, Bloat key)
    {
        System.out.println("Search by "+t+": "); 
        System.out.println(key);
        int i = searchBy(t,key);
        if (i >= 0)
        {
            System.out.println("matches");
            System.out.println(bloatList.get(i));
        }
        else
        {
            System.out.println("is between");
            i = -i-1;
            Bloat b1 = (i == 0) ? null : bloatList.get(i-1);
            System.out.println(b1);
            Bloat b2 = (i >= bloatList.size()) ? null : bloatList.get(i);
            System.out.println("and");
            System.out.println(b2);
        }
    }
}

public class MultiBinarySearch {
    private static int N = 1000;
    public static void main(String[] args)
    {
        BloatProducer bloatProducer = new BloatProducer();
        for (int i = 0; i < N; ++i)
        {
            bloatProducer.produceMoreBloat();
        }

        System.out.println("testMonotonicity() returns "+
                bloatProducer.testMonotonicity());
        Bloat key;
        key = new Bloat(10*N, 20*N, 30*N);
        bloatProducer.showSearch(Bloat.Type.COST, key);
        bloatProducer.showSearch(Bloat.Type.SPACE, key);
        bloatProducer.showSearch(Bloat.Type.TIME, key);
        key = new Bloat(-10000, 0, 1000*N);
        bloatProducer.showSearch(Bloat.Type.COST, key);
        bloatProducer.showSearch(Bloat.Type.SPACE, key);
        bloatProducer.showSearch(Bloat.Type.TIME, key);
    }
}