Initializing generic constructor - java

When I do the following:
IMiniMap<String,Integer> map = new SimpleListMM<String,Integer>();
IMiniMap<Double,ArrayList<Object>> map2 = new SimpleListMM<Double,ArrayList<Object>>();
IMiniMap<String,Integer> map = new SimpleListMM<String,Integer>();
then I get an error saying that The constructor SimpleListMM<...,...>() is undefined. I'm not allowed to have setter methods and all I did in constructor is to assign ArrayList<K> smth and ArrayList<V>. Whats the approach for intializing generic constructors in classes? How should I fix that?
import java.util.*;
public class FastGetListMM<K,V> extends AbstractListMM<K,V> implements Comparator<K> {
// Comparator used to sort elements; may be null if elements are Comparable
public final Comparator<K> cmp = new Comparator<K>();
//private List<K> keys;;
//private List<V> values;
// Assume elements must be comparable
public FastGetListMM(ArrayList<K> keys, ArrayList<V> values)
{
super(keys, vals);
this.cmp = new Comparator<K>();
}
// Use the given comparator to sort the keys
public FastGetListMM(Comparator<K> cmp)
{
super(cmp);
//this.cmp = cmp;
}
#Override
public int indexOf(K key) {
return 0;
}
#Override
public V put(K key, V value) {
return null;
}
#Override
public int compare(K arg0, K arg1) {
// TODO Auto-generated method stub
return 0;
}
}
SimpleListMM class:
import java.util.*;
public class SimpleListMM<K,V> extends AbstractListMM<K,V> {
//protected ArrayList<K> keys;
//protected ArrayList<V> vals;
// No special parameters required
public SimpleListMM(ArrayList<K> keys, ArrayList<V> vals)
{
super(keys, vals);
}
// Scan through the list of keys linearly searching for the given
// key. If not present, return a negative number.
public int indexOf(K key)
{
K index = null;
for(int i = 0; i < keys.size(); i++)
{
if(keys.get(i) != key)
return -1;
else
index = keys.get(i);
}
return (Integer) index;
}
// Locate the given key and replace its binding with the given
// value. If not present, add the key and value onto the end of
// their respective lists.
public V put(K key, V value)
{
for(int i = 0; i < keys.size(); i++)
{
if(keys.get(i) == key)
vals.set((Integer)keys.get(i), value);
else
{
keys.add(key);
vals.add(value);
}
}
return (V)vals;
}
}

Your classes don't have a no-arg constructor, thus the compiler error. Add the proper constructor in both classes:
public class SimpleListMM<K,V> extends AbstractListMM<K,V> {
public SimpleListMM() {
//some initialization logic
//maybe like this
super(new ArrayList<K>(), new ArrayList<V>());
}
public SimpleListMM(ArrayList<K> keys, ArrayList<V> vals) {
super(keys, vals);
}
}

Related

binarySearch with generics and capture of

I have a Task:
public interface Task {
}
Then I have implementations for those:
public interface Task__Init extends Task {
void init(Element e);
}
public interface Task__Hit_Test extends Task {
boolean hit_test(Element e, float x, float y);
}
public interface Task__Draw extends Task {
void draw(Element e);
}
I also have a class that can hold a instance of those implementations:
static public class Task_Holder<T extends Task> {
public int task_id;
public Task_Type type;
public T task;
// ...
}
Then I have a class that holds those, where the last ArrayList holds all of them (all_task_holders)
static public class Implementation_Context {
public HashMap<String, ArrayList<Task_Holder<Task__Init>>> init_solvers = new HashMap<>();
public HashMap<String, ArrayList<Task_Holder<Task__Draw>>> draw_solvers = new HashMap<>();
public HashMap<String, ArrayList<Task_Holder<Task__Hit_Test>>> hit_test_solvers = new HashMap<>();
public ArrayList<Task_Holder<? extends Task>> all_task_holders = new ArrayList<>();
// ...
}
Now one of the problem arises:
static public Task_Holder<?> find_task_holder(int task_id) {
Comparator<Task_Holder<?>> comparator = (a, b)-> {
if (a.task_id < b.task_id) return -1;
if (a.task_id > b.task_id) return 1;
return 0;
};
Collections.sort(ctx.implementation.all_task_holders, comparator);
Task_Holder<?> key = new Task_Holder<>();
key.task_id = task_id;
int index = Collections.binarySearch(ctx.implementation.all_task_holders, key);
for (Task_Holder<?> th : ctx.implementation.all_task_holders) {
if (th.task_id == task_id) {
return th;
}
}
assert false; // should we find things that are not there?
return null;
}
For the binarySearch I get (I make it a codeblock here, else stackoverflow removes words for some reason?):
The method binarySearch(List<? extends Comparable<? super T>>,
T) in the type Collections is not applicable for the arguments
(ArrayList<sfjl_ui.Task_Holder<?>>, sfjl_ui.Task_Holder<capture#6-of
?>)
I have no clue how to fix this. Every attempt breaks other things (for example I break the sort that's 3 lines higher).
It feels like paying off credit card debts with other credit cards, you never win.
How can I fix this?
Pass the comparator as an additional argument:
int index = Collections.binarySearch(ctx.all_task_holders, key, comparator);

Hashmap with a .class object as a key

I've created a hashmap with .class objects for keys.
Hashmap<Class<? extends MyObject>, Object> mapping = new Hashmap<Class<? extends MyObject>, Object>();
This is all well and fine, but I'm getting strange behaviour that I can only attribute to strangeness with the hash function. Randomly during runtime, iterating through the hashmap will not hit every value; it will miss one or two. I think this may be due to the .class object not being final, and therefore it changes causing it to map to a different hash value. With a different hash value, the hashmap wouldn't be able to correctly correlate the key with the value, thus making it appear to have lost the value.
Am I correct that this is what is going on? How can I work around this? Is there a better way to accomplish this form of data structure?
Edit: I really thought I was onto something with the hash function thing, but I'll post my real code to try and figure this out. It may be a problem with my implementation of a multimap. I've been using it for quite some time and haven't noticed any issues until recently.
/**
* My own implementation of a map that maps to a List. If the key is not present, then
* the map adds a List with a single entry. Every subsequent addition to the key
* is appended to the List.
* #author
*
* #param <T> Key
* #param <K> Value
*/
public class MultiMap<T, K> implements Map<T, List<K>>, Serializable, Iterable<K> {
/**
*
*/
private static final long serialVersionUID = 5789101682525659411L;
protected HashMap<T, List<K>> set = new HashMap<T, List<K>>();
#Override
public void clear() {
set = new HashMap<T, List<K>>();
}
#Override
public boolean containsKey(Object arg0) {
return set.containsKey(arg0);
}
#Override
public boolean containsValue(Object arg0) {
boolean output = false;
for(Iterator<List<K>> iter = set.values().iterator();iter.hasNext();) {
List<K> searchColl = iter.next();
for(Iterator<K> iter2 = searchColl.iterator(); iter2.hasNext();) {
K value = iter2.next();
if(value == arg0) {
output = true;
break;
}
}
}
return output;
}
#Override
public Set<Entry<T, List<K>>> entrySet() {
Set<Entry<T, List<K>>> output = new HashSet<Entry<T,List<K>>>();
for(Iterator<T> iter1 = set.keySet().iterator(); iter1.hasNext();) {
T key = iter1.next();
for(Iterator<K> iter2 = set.get(key).iterator(); iter2.hasNext();) {
K value = iter2.next();
List<K> input = new ArrayList<K>();
input.add(value);
output.add(new AbstractMap.SimpleEntry<T,List<K>>(key, input));
}
}
return output;
}
#Override
public boolean isEmpty() {
return set.isEmpty();
}
#Override
public Set<T> keySet() {
return set.keySet();
}
#Override
public int size() {
return set.size();
}
#Override
public Collection<List<K>> values() {
Collection<List<K>> values = new ArrayList<List<K>>();
for(Iterator<T> iter1 = set.keySet().iterator(); iter1.hasNext();) {
T key = iter1.next();
values.add(set.get(key));
}
return values;
}
#Override
public List<K> get(Object key) {
return set.get(key);
}
#Override
public List<K> put(T key, List<K> value) {
return set.put(key, value);
}
public void putValue(T key, K value) {
if(set.containsKey(key)) {
set.get(key).add(value);
}
else {
List<K> setval = new ArrayList<K>();
setval.add(value);
set.put(key, setval);
}
}
#Override
public List<K> remove(Object key) {
return set.remove(key);
}
public K removeValue(Object value) {
K valueRemoved = null;
for(T key:this.keySet()) {
for(K val:this.get(key)) {
if(val.equals(value)) {
List<K> temp = this.get(key);
temp.remove(value);
valueRemoved = val;
this.put(key, temp);
}
}
}
return valueRemoved;
}
#Override
public void putAll(Map<? extends T, ? extends List<K>> m) {
for(Iterator<? extends T> iter = m.keySet().iterator(); iter.hasNext();) {
T key = iter.next();
set.put(key, m.get(key));
}
}
#Override
public Iterator<K> iterator() {
return new MultiMapIterator<K>(this);
}
}
Perhaps there is an issue with my iterator? I'll post that code as well.
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class MultiMapIterator<T> implements Iterator<T> {
private MultiMap <?, T> map;
private Iterator<List<T>> HashIter;
private Iterator<T> govIter;
private T value;
public MultiMapIterator(MultiMap<?, T> map) {
this.map = map;
HashIter = map.values().iterator();
if(HashIter.hasNext()) {
govIter = HashIter.next().iterator();
}
if(govIter.hasNext()) {
value = govIter.next();
}
}
#Override
public boolean hasNext() {
if (govIter.hasNext()) {
return true;
}
else if(HashIter.hasNext()) {
govIter = HashIter.next().iterator();
return this.hasNext();
}
else {
return false;
}
}
#Override
public T next() {
if(!this.hasNext()) {
throw new NoSuchElementException();
}
else {
value = govIter.next();
return value;
}
}
#Override
public void remove() {
map.remove(value);
}
}
Sorry for the long tracts of code. Thank you for spending time helping me with this.
You pull the a value out of govIter in the constructor, but never return it.
Your iterator remove method is completely wrong. You are iterating values, but calling the map.remove which removes by key. you simply want to call govIter.remove() (unless you need to avoid empty lists, in which case it's more complicated).
Your hasNext() method could also have problems depending on whether or not you allow empty Lists values in your multimap.

Set ordered by "add() count"

I'm trying to implement a Set which is ordered by the count of additions like this:
public class App {
public static void main(String args[]) {
FrequencyOrderedTreeSet<String> set = new FrequencyOrderedTreeSet<String>();
set.add("bar");
set.add("foo");
set.add("foo");
Iterator<String> i = set.iterator();
while (i.hasNext()) {
System.out.print(i.next());
}
// prints "foobar"
}
}
I've created a protected class FrequencyOrderedTreeSet.Element which implements Comparable and has a T entry and an int frequency property and extended TreeSet<FrequencyOrderedTreeSet.Element> with FrequencyOrderedTreeSet<T> and overrode the compareTo and equals methods on the Element.
One problem is that I can't override the add() method because of type erasure problems and also I can't call instanceof Element in the equals method, because in case object given to it is an Element, I have to compare their entries, but if it's not, I have to compare the object itself to this.entry.
In the add method I create a new element, find the element with the same entry in the set, set the frequency on the new element to "old+1", remove the old one and add the new one. I'm not even sure this is the best way to do this or if it would work even because the other problems I described.
The question is: what's the best way to implement such data structure? In case I'm somehow on the right track - how can I circumvent the problems I've mentioned above?
Here's a basic implementation. It's not the most optimal and will take some more work if you want to implement the full Set interface.
public class FrequencySet<T> implements Iterable<T>
{
private TreeSet<T> set;
private HashMap<T, Integer> elements = new HashMap<T, Integer>();
public FrequencySet()
{
set = new TreeSet<T>(new Comparator<T>()
{
public int compare(T o1, T o2)
{
return elements.get(o2)-elements.get(o1);
}
});
}
public void add(T t)
{
Integer i = elements.get(t);
elements.put(t, i == null ? 1 : i+1);
set.remove(t);
set.add(t);
}
public Iterator<T> iterator() {return set.iterator();}
public static void main(String [] args)
{
FrequencySet<String> fset = new FrequencySet<String>();
fset.add("foo");
fset.add("bar");
fset.add("foo");
for (String s : fset)
System.out.print(s);
System.out.println();
fset.add("bar");
fset.add("bar");
for (String s : fset)
System.out.print(s);
}
}
The key is in the add method. We change the counter for the given object (which changes the relation order), remove it from the backing set and put it back in.
This works the other way (count is increased when you use GET)
#SuppressWarnings("rawtypes")
final class Cache implements Comparable {
private String key;
private String value;
private int counter;
public String getValue() {
counter++;
return value;
}
private void setValue(String value) { this.value = value; }
public String getKey() { return key; }
private void setKey(String key) { this.key = key; }
public int getCounter() { return counter; }
public void setCounter(int counter) { this.counter = counter; }
public Cache(String key, String value) {
this.setKey(key);
this.setValue(value);
setCounter(0);
}
#Override
public int compareTo(Object arg0) {
if(!(arg0 instanceof Cache)) {
throw new ClassCastException();
}
return this.getCounter() - ((Cache) arg0).getCounter();
}
}

adding values in list with user defined class

i am new to andoird and i am using list with custom defined class but i am not sure how to add my key value pair in this list
here is my code
public class Pair<K,V> {
private K k;
private V v;
public Pair(K k,V v)
{
this.k=k;
this.v=v;
}
public K getK()
{
return k;
}
public void setK( K k)
{
this.k=k;
}
public V getV()
{
return v;
}
public void setV(V v)
{
this.v=v;
}
}
and
List<Pair<String,String>> pl = new ArrayList<Pair<String,String>>();
I tried
pl.add(Pair("name","ahsen"));
pl.addAll(Pair("name","ahsen"));
but its not working
am i missing something or its just missing new operator ?
pl.add(new Pair("name","ahsen"));
pl.addAll(new Pair("name","ahsen"));
You are missing a new operator.
pl.add(new Pair("name","ahsen"));
You can use a HashMap for key/value pairs.

How to declare final HashMap that should not allow to update or remove element

I have a hash map like,
public static void main(String[] args) {
final Map<String, String> daysMap = new HashMap(7);
daysMap.put("1", "Sunday");
daysMap.put("2", "Monday");
daysMap.put("3", "Tuesday");
daysMap.put("4", "Wednesday");
daysMap.put("5", "Thursday");
daysMap.put("6", "Friday");
daysMap.put("7", "Saturday");
}
In this map
1. Should not allow to put more than 7 elements
2. Should not update value for corresponding key [like daysMap.put("5", "xxx");]
3. Should not allow to remove any key
How to do?
You can implement a new HashMap
public class CoolMap<K, V> extends HashMap<K, V> {
#Override
public V put(K key, V value) {
if (size() == 7) {
throw new IllegalStateException("Size is at max!");
} else {
// If there is something already with that key
if (containsKey(value)) {
// do nothing
return value;
} else {
// put inside
return super.put(key, value);
}
}
}
#Override
public void putAll(Map<? extends K, ? extends V> collection) {
if (collection.size() > 7) {
throw new IllegalStateException("Size is at max!");
} else {
super.putAll(collection);
}
}
#Override
public V remove(Object key) {
return null;// doesn't remove anything
}
Points 2 and 3 are covered by Collections.unmodifiableMap. To cover the first point, you can add an hand written test.
As has been already discussed ,the Points 2 and 3 are covered like this
import java.util.*;
public class OP2 {
public static void main(String[] s) {
//object hash table
Hashtable<String,String> table = new Hashtable<String,String>();
table.
// populate the table
table.put("1", "Sunday");
table.put("2", "Monday");
table.put("3", "Tuesday");
table.put("4", "Wednesday");
table.put("5", "Thursday");
table.put("6", "Friday");
table.put("7", "Saturday");
System.out.println("Initial collection: "+table);
// create unmodifiable map
Map m = Collections.unmodifiableMap(table);
// try to modify the collection
// m.put("key3", "value3");
//Uncomment the above line and an error is obtained
}
}
Moreover for the first problem it would be better to call a function when you populate your map:-
public boolean putAndTest(MyKey key, MyValue value) {
if (map.size() >= MAX && !map.containsKey(key)) {
return false;
} else {
map.put("Whatever you want");
return true;
}
}
Why donĀ“t you create your own object that contains a private hashmap and then you can allow what methods on that private hashmap that are made public?

Categories