When I tried to write the following line:
int foundIndex = Collections.<K>binarySearch(keys, key);
it shows the error: The parameterized method <K>binarySearch(List<? extends Comparable<? super K>>, K) of type
Collections is not applicable for the arguments (List<K>, K)
What does the above error mean and what did I do wrong in my code?
// Comparator used to sort elements; may be null if elements are Comparable
public final Comparator<K> cmp;
{
super(new ArrayList<K>(), new ArrayList<V>());
cmp = new MyComparator<K>();
}
// Use the given comparator to sort the keys
//super(new ArrayList<K>(), new ArrayList<V>());
this.cmp = cmp;
}
{
if(!(key instanceof Comparable) && cmp == null)
throw new RuntimeException("The key is not instance of Comparable or comparator object is null");
}
public int indexOf(K key)
{
int foundIndex = Collections.<K>binarySearch(keys, key);
return foundIndex;
}
public int compareTo(K otherKey)
{
int result = 0;
for(int i = 0; i < keys.size(); i++)
{
result = ((Comparable<K>) keys.get(i)).compareTo(otherKey);
}
return result;
}
MyComparator class
import java.util.Comparator;
#Override
public int compare(K key1, K key2)
{
return -1;
}
}
Your problem is that FastGetListMM<K, V> is implementing Comparable<K> but that Collections.<K>binarySearch(list, value) is expecting a list of Comparable<K>.
It is K that should implement Comparable<K>, not FastGetListMM. If you want to use Collections.<K>binarySearch(keys, key) you need FastGetListMM to implement List<Comparable<K>> and not Comparable<K> - and make sure that all the items in FastGetListMM are arranged in ascending order.
To use that implementation of binary search you need K to implement comparable there is another function that receives the comparable itself. In your case you need to call Collections.<K>binarySearch(keys, key, new MyComparator());
Related
Ok, so I'm I'm working on a school project where we implement a Binary TreeMap and given a basic template to fill out. I'll try to not dump all of the code but here's where I'm hitting a wall. I need to be able to compare keys so insert new elements, properly search and whatnot. But I keep getting a Bad Operand error.
private class Element {
K key;
V value;
public Element(K key, V value) {
this.key = key;
this.value = value;
}
public int compareTo(Element that) {
if (key < that.key) //Error Here
return -1;
else if(key > that.key) //And here
return 1;
else
return 0;
}
}
Now this class is a subclass of the TreeMap class. Again I won't dump the whole code, but the header is like so:
public class TreeMap<K extends Comparable<K>,V> implements MyMap<K,V>
Now everywhere I look seems to point that having K extends Comparable<K> should allow these to be comparable, but they're not. This header was provided by the teacher, so I don't think it needs to be altered. Am I just overlooking or forgetting something?
You can't compare Comparable objects using < and >. Those are only for numeric values. Instead, you can use something like this:
public int compareTo(Element that) {
final int comp = key.compareTo(that.key);
if (comp < 0)
return -1;
else if(comp > 0)
return 1;
else
return 0;
}
Or, better, just return the result of calling compareTo():
public int compareTo(Element that) {
return key.compareTo(that.key);
}
I have the following method that looks for the vectors (lists of double) that are similar to the input vector v in allVectors and return their indices (list of int):
public List returnSimilar(List v,List<List<Double>> allVectors);
Now if v is a List<Double> I would like the method to execute a certain set of statements (A-statements) and return List<Integer>. If v is a List<List<Double>> I would like the method to execute another set of statements (B-statements) and return List<List<Integer>>.
How can this be done?
Make your method generic:
public <T> List<Integer> returnSimilar(List<T> v, List<List<T>> allVectors);
If you really need to implement logic that differs from T - introduce overloaded methods.
public <T> List<Integer> returnSimilar(List<T> v, List<List<T>> allVectors) {
List<Integer> result = new ArrayList<>();
for(int i = 0; i < allVectors.size(); i++) {
if (allVectors.get(i).isSimilar(v)) {
result.add(i);
}
return result;
}
public <T> boolean isSimilar(List<T> a, List<T> b) {
if (a.size() != b.size()) return false;
for (int i = 0; i < a.size(); i++) {
if (!a.get(i).equals(b.get(i))) {
return false;
}
return true;
}
I have to implement an ArrayList and a sorting method for the list. The list is holding objects of the same type. When i try to sort the list using my own implementation I get this error:
The method insertionSort(T[]) in the type ArrayList is not applicable for the arguments (List)
I realize it wants an array passed to it, but how can I pass the list.. or just get it to work. I've been working on it for a while, checked my book, lecture notes, etc. and can't figure it out.
Student class(the objects the list will hold)
public class Student implements Serializable, Comparable<Student>
{
public int compareTo(Student other)
{
if (this.lastName.equals(other.lastName))
return this.firstName.compareTo(other.firstName);
else if (other.getlastName().compareTo(this.getlastName()) < 0)
return 0;
else if (other.getlastName().compareTo(this.getlastName()) > 0)
return -1;
else
return 1;
}
}
The actual ArrayList
public class ArrayList<T> implements Iterable<T>, List<T>
{
protected final int DEFAULT_CAPACITY = 20;
private final int NOT_FOUND = -1;
protected int rear;
protected T[] list;
#SuppressWarnings("unchecked")
public ArrayList()
{
rear = 0;
list = (T[])(new Object[DEFAULT_CAPACITY]);
}
public static <T extends Comparable<? super T>> void insertionSort(T[] a)
{
for(int index = 0; index < a.length; index++)
{
T key = a[index];
int position = index;
while(position > 0 && a[position-1].compareTo(key) > 0)
{
a[position] = a[position-1];
position--;
}
a[position] = key;
}
}
}
The easiest way I can think of, would be to modify your insertionSort method to take a List<T>. Something like,
public static <T extends Comparable<? super T>> void insertionSort(List<T> a) {
final int len = a.size(); // <-- from a.length
for (int index = 0; index < len; index++) {
T key = a.get(index); // <-- from a[index]
int position = index;
while (position > 0 && a.get(position - 1).compareTo(key) > 0) {
a.set(position, a.get(position - 1)); // from a[position] = a[position-1];
position--;
}
a.set(position, key); // <-- from a[position] = key;
}
}
If you want that method to apply only to your ArrayList:
public static <T extends Comparable<? super T>> void insertionSort(ArrayList<T> list)
{
T[] a = list.list;
...
take the whole list as parameter and get it's internal array directly
When I try to access a generic method from my main class it gives me an error.
When I do the following:
Integer key = map.remove(15);
then Eclipse says "The method remove(String) in the type IMiniMap<String,Integer> is not applicable for the arguments (int)" What's the way to access a method of generic type?
public class Tester {
public static void main(String[] args)
{
IMiniMap<String,Integer> map = new SimpleListMM<String,Integer>();
map.put("B",15);
map.put("A",5);
map.put("R",-5);
map.put("D",55);
map.put("Poems",128);
map.put("Plays",256);
// System.out.println(map.size());
// map.put("B", 22);
// System.out.println(map.keys());
//System.out.println(map.toString());
Integer key = map.remove(15);
}
}
public abstract class AbstractListMM<K,V> implements IMiniMap<K,V>{
protected List <K> keys;
protected List <V> vals;
// Initialize the lists of keys and values with a concrete instance
public AbstractListMM()
{
this.keys = new ArrayList<K>();
this.vals = new ArrayList<V>();
}
public AbstractListMM(List <K> keys, List <V> vals)
{
this.keys = keys;
this.vals = vals;
}
// Return the number of bindings based on the size of the key list
public int size()
{
return keys.size();
}
// Based on the lists size
public boolean isEmpty()
{
return (keys.isEmpty() && vals.isEmpty());
}
// Make a (shallow) copy of the keys list and return it
public List<K> keys()
{
List<K> newKeys = this.keys;
return newKeys;
}
// Make a (shallow) copy of the vals list and return it
public List<V> values()
{
List<V> vals = this.vals;
return vals;
}
// Use this.indexOf() to locate the given key as quickly as possible
public boolean contains(K key)
{
int pos = this.indexOf(key);
if(pos < 0)
return false;
else
return true;
/*if(this.indexOf(key) < 0)
return false;
else
return true;*/
}
// Use this.indexOf() to determine if a given key is present and
// return its associated value; return null if the key is not
// present
//
// TARGET COMPLEXITY: Same speed as indexOf()
public V get(K key)
{
int pos = this.indexOf(key);
if(pos < 0)
return null;
else
return vals.get(pos);
}
// Use this.indexOf() to determine the location of the given
// key/value and remove it from the corresponding lists
//
// TARGET COMPLEXITY: O(N) due to list elements shifting
public V remove(K key)
{
int pos = this.indexOf(key);
if(pos < 0)
return null;
else
return vals.remove(pos);
}
// Find the numeric index of the key as quickly as possible based on
// the type of ListMM being implemented. Return a negative number if
// the given key is not present.
public abstract int indexOf(K key);
// Associate the given key with the given value in the
// lists. Creates an ordering of keys that is compatible with how
// indexOf() works to locate keys.
public abstract V put(K key, V value);
}
You already specify that K type
AbstractListMM<K,V> implements IMiniMap<K,V>
will be a type String which is from here:
IMiniMap<String,Integer> map = new SimpleListMM<String,Integer>();
And therefore you need to supply your remove method remove(K key) as a String not an Integer
map.remove("B");
What I want to do is use the compareTo() method to compare removedItemFromList1 and removedItemFromList2, then insert whichever value is smaller into the modifiedList3 and put the larger of the two removedFromList 1 or 2 back into its original list. If I had hair long enough to pull, it would have been pulled out by now...Am I not casting correctly? How do I correctly go about using the compareTo() method to accomplish this?
public class List<Integer> implements Comparable
{
private ListNode<Integer> firstNode;
private ListNode<Integer> lastNode;
public void insertAtBack (Integer insertItem)
{
if ( isEmpty())
firstNode = lastNode = new ListNode<Integer>(insertItem);
else
lastNode = lastNode.nextBasket = new ListNode<Integer>( insertItem );
}
public Integer removeFromBack()
{
Integer removedItem = (Integer) lastNode.topBucketInBasket;
if ( firstNode == lastNode)
firstNode = lastNode = null;
else
{
ListNode<Integer> current = firstNode;
while ( current.nextBasket != lastNode)
current = current.nextBasket;
lastNode = current;
current.nextBasket = null;
}
return removedItem;
}
public boolean isEmpty()
{
return firstNode == null;
}
public List<Integer> merge(List<Integer> list1, List<Integer> list2)
{
List<Integer> modifiedList3 = new List<Integer>();
Integer removedItemFromList1 = (Integer) list1.removeFromBack();
Integer removedItemFromList2 = (Integer) list2.removeFromBack();
((Comparable) removedItemFromList1).compareTo( removedItemFromList2);
int comparison = compareTo(removedItemFromList2);
if ( comparison == 1)
modifiedList3.insertAtBack(removedItemFromList2);
list1.insertAtBack(removedItemFromList1);
if ( comparison == -1)
modifiedList3.insertAtBack(removedItemFromList1);
list2.insertAtBack(removedItemFromList2);
return modifiedList3;
}
#Override
public int compareTo(Integer itemToCompare)
{
final int BEFORE = -1;
final int AFTER = 1;
if (this.removedItemFromList1 < list2.removedItemFromList2) return BEFORE;
if (this.removedItemFromList1 > list2.removedItemFromList2) return AFTER;
}
}
You should implement the generic version Comparable<Integer> instead of the raw version Comparable.
Also, in the following
public class List<Integer> implements Comparable
That Integer is not the same as java.lang.Integer. Actually, it's something called formal type parameter in that context.
You probably want to change it to
//List is kind of ambiguous with java.util.List
public class MyList<E> implements Comparable<Integer> {
or may be something else instead of MyList.
If you implement Comparable it should be
#Override
public int compareTo(Object itemToCompare) {
and if Comparable<Integer> (which is the one you are after, I guess), it should be
#Override
public int compareTo(Integer itemToCompare)
The difference is the parameter types - Object and Integer.
It's kind of messy and not so clear what you are trying to acheive.
But the point that your List class implements Comparable indicates that you want to compare an instance of List with another instance. If that's the case then it should like something like this -
public class MyList<E> implements Comparable<MyList> {
#Override
public int compareTo(MyList other) {
//compare and return result
}
But the fact that the parameter type is Integer suggest that what you are actually trying to compare are Integers, in which case Integer is already Comparable.
((Comparable) removedItemFromList1).compareTo( removedItemFromList2);
You don't need to do all that
removedItemFromList1.compareTo(removedItemFromList2);
is enough. And if that's all you need then you don't need implement Comparable at all, so can remove that compareTo method also.
The Comparable interface goes this way
public interface Comparable<T> {
public int compareTo(T t){
}
}
You should use the Type Parameter. Comparable is Type Parametrized.
So try it this way...
public class mList<Integer> implements Comparable<Integer>{
......
public int compareTo(Integer itemToCompare){
.....
}
}