crush
crush

Reputation: 17023

Java Comparable to Instance or String

I'm trying to create a class that can either be compared to an instance of the same class, or to String.

For example, consider the following:

public class Record implements Comparable<Record> {
    public String name;

    public Record(String name) {
        this.name = name;
    }

    public int compareTo(Record o) {
        return name.compareTo(o.name);
    }
}

I then place this into an ArrayList as follows:

ArrayList<Record> records = new ArrayList<Record>();
records.add(new Record("3"));
records.add(new Record("1"));
records.add(new Record("2"));

If I then sort them, they are sorted properly:

Collections.sort(records);

However, I not want to be able to get a record via binary search based on a string. For example:

int index = Collections.binarySearch(records, "3");

The problem is that there is no compareTo method that takes a String as argument, and I'm unsure how to implement it.

I tried doing:

public class Record implements Comparable<Record>, Comparable<String> {
    public String name;

    public Record(String name) {
        this.name = name;
    }

    public int compareTo(Record o) {
        return name.compareTo(o.name);
    }

    public int compareTo(String o) {
        return name.compareTo(o);
    }
}

But, of course, you cannot implement the same interface with different arguments more than once.

So, I'm looking for a method to do the above. I have looked at the following previous answers, but have not found one that truly answers this sufficiently. At least, if it did, I did not understand it.

Basically, what I want to do is the following:

public int compare(Record r, String s) {
    return r.name.compareTo(s);
}

As far as I can tell, though, you cannot compare objects of differing types without implementing some sort of common interface or superclass. I don't really have that option with String.

Can someone please show me how to do this, if it is possible? Thanks.

UPDATE I realize that I could do the following:

Collections.binarySearch(records, new Record("3"));

But, that is not what I'm after. Thanks.

Upvotes: 2

Views: 2687

Answers (4)

Paul Vargas
Paul Vargas

Reputation: 42040

You can try the next for getting the index in the sorted collection:

class Record implements Comparable<String> {

    public String name;

    public Record(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(String o) {
        return name.compareTo(o);
    }

}

And:

public static void main(String[] args) {

    ArrayList<Record> records = new ArrayList<Record>();
    records.add(new Record("3"));
    records.add(new Record("1"));
    records.add(new Record("2"));

    Collections.sort(records, new Comparator<Record>() {
        @Override
        public int compare(Record a, Record b) {
            return a.name.compareTo(b.name);
        }
    });

    int index = Collections.binarySearch(records, "3");
    System.out.println(index); // 2

}

Upvotes: 1

Alpedar
Alpedar

Reputation: 1344

You cannot do that. from javadoc

It follows immediately from the contract for compareTo that the quotient is an equivalence relation on C and String's compareTo will never return true for your Record.

What you could do, is create Comparator that would compare Strings and Records. Just leave it without generics.

Upvotes: 1

arcy
arcy

Reputation: 13133

Is there some problem with defining the interface ComparableToString and implementing it? Its compareTo method can restrict callers to String. No instanceof, no casting required.

    public class Record implements Comparable<Record>, ComparableToString
    {
        public String name;

        public Record(String name)
        {
            this.name = name;
        }

        public int compareTo(Record o)
        {
            return name.compareTo(o.name);
        }

        public int compareTo(String o)
        {
            return name.compareTo(o);
        }
    }
    interface ComparableToString
    {
        public int compareTo(String s);
    }

Upvotes: 0

Ian McMahon
Ian McMahon

Reputation: 1700

You can implement Comparable without qualifying it with a type, and check the incoming Object with instanceof, and behave differently depending on what type you receive.

Upvotes: 4

Related Questions