ishandutta2007
ishandutta2007

Reputation: 1

Java Collections Comparable wrong 3rd argument type in Collections.binarySearch()

I am trying to use Binary search using Collections.binarySearch();

I need to compared based on mId field of the Item .

The compilation error is:

Found 'java.util.comparator' Required 'java.util.comparator < ? super java.lang.comparable < ? extends java.lang.comparable < ? extends java.lang.comparable < ? >>>>'

public class SomeOuterClass {
public static class Item implements Comparable<Item> {
    static long id = 0;
    public Boolean isSaved;
    public Boolean isLoved;

    long mId;
    Post post;

    public Item(Post p) {
        mId = id++;
        post = p;
        isSaved = Boolean.FALSE;
        isLoved = Boolean.FALSE;
    }

    long getId() {
        return mId;
    }

    @Override
    public int compareTo(Item o) {
        return Comparators.ID.compare(this, o);
    }


    public static class Comparators {
        public static Comparator<Item> TITLE = new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return o1.post.title().compareTo(o2.post.title());
            }
        };
        public static Comparator<Item> ID = new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return (int) (-(o1.mId - o2.mId));//I am putting a minus to indicate list is in descending order
            }
        };
    }

}

private List<Item> items = new ArrayList<Item>();

public Item findByBinSrach(int itemId) {
    int index = Collections.binarySearch(items, itemId, Item.Comparators.ID);//Here it is not recognizing the 3rd parameter
    return getItem(index);
}}

Upvotes: 0

Views: 359

Answers (1)

Andy Turner
Andy Turner

Reputation: 140319

The second parameter should be the Item you are looking for, not its itemId. Collections.binarySearch has no way of knowing how to relate an int to an Item.

You might find it easier to store items as a LinkedHashMap<Integer, Item> (if you require insertion order to be preserved; you can use HashMap if you don't care about order), where the key is the itemId. Then, you can simply use return items.get(itemId).

Two other points:

  1. It is generally a bad idea to have side effects in constructors (in this case, incrementing id): it makes testing (amongst other things) hard. It would be better to inject the mId as a constructor parameter;
  2. Make mId final, in order that it can't be changed post-construction - this is especially relevant if you adopt the Map suggestion above, since you wouldn't want the map key to be different to the value returned.

Upvotes: 1

Related Questions