Treemap Constructor - java

Is the way I am trying to setup my treemap constructor correct?
import java.util.TreeMap ;
public class Table<K extends Comparable<K>, T> { //K = Key, T = Item
TreeMap<K, T> tm;
public Table<K, T> () {
tm = new TreeMap<K, T>();
}
public boolean isEmpty() {
return tm.isEmpty();
}
public int size() {
return tm.size();
}
public void tableInsert(K key, T item) throws TableException {
tm.put(key, item);
}
public boolean tableDelete(K key) {
if (tm.containsKey(key)) {
tm.remove(key);
return true;
} else {
return false;
}
}
public T tableRetreive(K key) {
return tm.get(key);
} //return null if not found
public void printTable() {
TreeMap<K, T> tmclone = (TreeMap<K, T>) tm.clone();
while (!tmclone.isEmpty()) {
System.out.println(tmclone.pollFirstEntry());
}
} //print in search key order
}
I have another class that will create students, and with the put method will insert into a new map tree.. but the compiler says it was expecting a different character. Also, is the proper way to call the constructor is to input TreeMap blah<K,T> = new TreeMap correct?

This code here:
public Table<K, T> () {
tm = new TreeMap<K, T>();
}
needs to change to this:
public Table() {
tm = new TreeMap<K, T>();
}
Otherwise all good.

If you are asking if the initialization in the constructor is functional(?), yes. You could also make an initializer above the constructor like this:
public class Table <K extends Comparable<K>, T> { //K = Key, T = Item
TreeMap<K,T> tm;
{ //Initializer
tm = new TreeMap<K,T>();
}
public Table<K,T>() {
//Your constructor here
}
//Other methods...
}
As far as the second part of your question, there is far too little based on your description to diagnose the issue without seeing some more code and getting more details.

Related

Strange bug with Streams

So I have created my own Set, which is just a regular set, but has additional functions (for example my set only stores absolute values).
Here is my Code:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet<E> extends HashSet<E> {
private Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<Integer>();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(E e){
return mySet.add(Math.abs((Integer) e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o){
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends E> c) {
List<Integer> myList = new ArrayList<>();
for (Object e: c) {
myList.add(Math.abs((Integer) e));
}
return mySet.addAll(myList);
}
#Override
public String toString(){
return mySet.toString();
}
}
I had a test case in JUnit, which failed. Because there was some issue with my code. For demonstration purpose, and for me to explain my issue better I have created two functions, which show the problem well.
Here is the problem:
public static void testSortedByAbsoluteValueIntegerSet() {
Set<Integer> set1 = new SortedByAbsoluteValueIntegerSet();
Set<Integer> set2 = new HashSet<>();
set1.add(5);
set1.add(3);
set2.add(5);
set2.add(3);
String x = toString(set1); //x is ""
String t = toString(set2); //t is "3 5"
}
public static String toString(final Collection<Integer> collection) {
return String.join(" ", collection.stream()
.map(i -> Integer.toString(i))
.toArray(String[]::new));
}
So the problem arises in this line:
String x = toString(set1); //x is always an empty string
String t = toString(set2); //t works correctly
When I go through debugger I see that String x is always an empty String and String t works correctly. By the way set1 is representation of my created set and set2 is just a regular hashset.
The question is: how can I fix my SortedByAbsoluteValueIntegerSet class so that the toString() method worked fine with my own created set as well.
P.S I am new to streams and I don't really understand the problem, why does it happens.
It's because you're extending HashSet but also using an internal Set.
When adding, you're adding to the internal Set but when using collection.stream() it calls the inherited HashSet (which is empty).
Easiest for you I beleive would be to remove the internal 'mySet' and call the inherited methods in your overridden methods.
For instance, your add method would be
#Override
public boolean add(E e){
return super.add(Math.abs((Integer) e));
}
(and then you don't need to override size, remove, contains of toString or spliterator)
Full example:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {
#Override
public boolean add(Integer e){
return super.add(Math.abs(e));
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e: c) {
myList.add(Math.abs(e));
}
return super.addAll(myList);
}
}
I think Tomas F gave better answer
Main problem in your set is using HashSet mySet as field and extending HashSet. In java better to use (field) composition instead of extending to add some functionality to your class. Here you tried use both - it's not a good idea.
Best decision is to use just composition and extending more general class, for example AbstractSet<Integer> and Set<Integer>:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends AbstractSet<Integer>
implements Set<Integer>, java.io.Serializable {
private final Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<>();
}
#Override
public Iterator<Integer> iterator() {
return mySet.iterator();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(Integer e) {
return mySet.add(Math.abs(e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o) {
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e : c) {
myList.add(Math.abs(e));
}
return mySet.addAll(myList);
}
#Override
public String toString() {
return mySet.toString();
}
}
in this case you don't have to implement spliterator, because Set has default implementation using this keyword (which is refer to your set as a Collection)
but also you can implement spliterator in your class (but using such extends and internal Set fields are the bad practice. Also, it's better to get rid of type parameter E and casting elements to Integer:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {
private Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<>();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(Integer e){
return mySet.add(Math.abs(e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o){
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e: c) {
myList.add(Math.abs(e));
}
return mySet.addAll(myList);
}
#Override
public String toString(){
return mySet.toString();
}
#Override
public Spliterator<Integer> spliterator() {
return mySet.spliterator();
}
}

Java - unmodifiable key set map

I am looking for a way to provide a Map with pre-defined (as in runtime immutable, not compile time const) constant key set, but modifiable values.
The JDK provides Collections.unmodifiableMap factory method, which wraps a Map and provides an immutable view of it.
Is there a similar way to wrap a Map so that only it's keys are immutable? For instance, put(K,V) will replace the value of existing keys, but throw UnsupportedOperationException if the key does not exist.
Use an enum as the key. Then one needn't care if they can add a new key since the key domain is fixed and finite. In fact, that's such a standard use case that Java provides java.util.EnumMap<K extends Enum<K>,V>
http://docs.oracle.com/javase/8/docs/api/java/util/EnumMap.html
Ok, all the solutions suggested here were to wrap or extend Collections.UnmodifiableMap. Both impossible since the original implementation would not allow to override put (and replace etc.), Which is exactly what makes it secure...
I see two options:
The "smelly" option - Using reflection to get hold of the original Map<> and directly call it's methods.
The "ugly" option - Copy the source of some of the static classes in java.lang.Collections and modify them.
If anyone has a better idea, please let me know.
Here is an initial implementation of the 2'nd solution:
import java.io.Serializable;
import java.util.*;
import java.util.function.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static java.util.Collections.unmodifiableCollection;
import static java.util.Collections.unmodifiableSet;
/**
* #serial include
*/
public class UnmodifiableKeySetMap<K,V> implements Map<K,V>, Serializable {
private final Map<K, V> m;
/**
* Returns a view of the specified map with unmodifiable key set. This
* method allows modules to provide users with "read-only" access to
* internal maps. Query operations on the returned map "read through"
* to the specified map, and attempts to modify the returned
* map, whether direct or via its collection views, result in an
* <tt>UnsupportedOperationException</tt>.<p>
*
* The returned map will be serializable if the specified map
* is serializable.
*
* #param <K> the class of the map keys
* #param <V> the class of the map values
* #param m the map for which an unmodifiable view is to be returned.
* #return an unmodifiable view of the specified map.
*/
public static <K,V> Map<K,V> unmodifiableKeySetMap(Map<K, V> m) {
return new UnmodifiableKeySetMap<>(m);
}
UnmodifiableKeySetMap(Map<K, V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
}
public int size() {return m.size();}
public boolean isEmpty() {return m.isEmpty();}
public boolean containsKey(Object key) {return m.containsKey(key);}
public boolean containsValue(Object val) {return m.containsValue(val);}
public V get(Object key) {return m.get(key);}
public V put(K key, V value) {
if (containsKey(key)) {
return m.put(key, value);
}
throw new UnsupportedOperationException();
}
public V remove(Object key) {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
private transient Set<K> keySet;
private transient Set<Map.Entry<K,V>> entrySet;
private transient Collection<V> values;
public Set<K> keySet() {
if (keySet==null)
keySet = unmodifiableSet(m.keySet());
return keySet;
}
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
entrySet = new UnmodifiableKeySetMap.UnmodifiableEntrySet<>(m.entrySet());
return entrySet;
}
public Collection<V> values() {
if (values==null)
values = unmodifiableCollection(m.values());
return values;
}
public boolean equals(Object o) {return o == this || m.equals(o);}
public int hashCode() {return m.hashCode();}
public String toString() {return m.toString();}
// Override default methods in Map
#Override
#SuppressWarnings("unchecked")
public V getOrDefault(Object k, V defaultValue) {
// Safe cast as we don't change the value
return ((Map<K, V>)m).getOrDefault(k, defaultValue);
}
#Override
public void forEach(BiConsumer<? super K, ? super V> action) {
m.forEach(action);
}
#Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException();
}
#Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
#Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
#Override
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
#Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
#Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
#Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
/**
* #serial include
*/
static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
implements Set<E>, Serializable {
private static final long serialVersionUID = -9215047833775013803L;
UnmodifiableSet(Set<? extends E> s) {super(s);}
public boolean equals(Object o) {return o == this || c.equals(o);}
public int hashCode() {return c.hashCode();}
}
/**
* #serial include
*/
static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 1820017752578914078L;
final Collection<? extends E> c;
UnmodifiableCollection(Collection<? extends E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
}
public int size() {return c.size();}
public boolean isEmpty() {return c.isEmpty();}
public boolean contains(Object o) {return c.contains(o);}
public Object[] toArray() {return c.toArray();}
public <T> T[] toArray(T[] a) {return c.toArray(a);}
public String toString() {return c.toString();}
public Iterator<E> iterator() {
return new Iterator<E>() {
private final Iterator<? extends E> i = c.iterator();
public boolean hasNext() {return i.hasNext();}
public E next() {return i.next();}
public void remove() {
throw new UnsupportedOperationException();
}
#Override
public void forEachRemaining(Consumer<? super E> action) {
// Use backing collection version
i.forEachRemaining(action);
}
};
}
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection<?> coll) {
return c.containsAll(coll);
}
public boolean addAll(Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
// Override default methods in Collection
#Override
public void forEach(Consumer<? super E> action) {
c.forEach(action);
}
#Override
public boolean removeIf(Predicate<? super E> filter) {
throw new UnsupportedOperationException();
}
#SuppressWarnings("unchecked")
#Override
public Spliterator<E> spliterator() {
return (Spliterator<E>)c.spliterator();
}
#SuppressWarnings("unchecked")
#Override
public Stream<E> stream() {
return (Stream<E>)c.stream();
}
#SuppressWarnings("unchecked")
#Override
public Stream<E> parallelStream() {
return (Stream<E>)c.parallelStream();
}
}
/**
* We need this class in addition to UnmodifiableSet as
* Map.Entries themselves permit modification of the backing Map
* via their setValue operation. This class is subtle: there are
* many possible attacks that must be thwarted.
*
* #serial include
*/
static class UnmodifiableEntrySet<K,V>
extends UnmodifiableSet<Entry<K,V>> {
private static final long serialVersionUID = 7854390611657943733L;
#SuppressWarnings({"unchecked", "rawtypes"})
UnmodifiableEntrySet(Set<? extends Map.Entry<? extends K, ? extends V>> s) {
// Need to cast to raw in order to work around a limitation in the type system
super((Set)s);
}
static <K, V> Consumer<Entry<K, V>> entryConsumer(Consumer<? super Entry<K, V>> action) {
return e -> action.accept(new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntry<>(e));
}
public void forEach(Consumer<? super Entry<K, V>> action) {
Objects.requireNonNull(action);
c.forEach(entryConsumer(action));
}
static final class UnmodifiableEntrySetSpliterator<K, V>
implements Spliterator<Entry<K,V>> {
final Spliterator<Map.Entry<K, V>> s;
UnmodifiableEntrySetSpliterator(Spliterator<Entry<K, V>> s) {
this.s = s;
}
#Override
public boolean tryAdvance(Consumer<? super Entry<K, V>> action) {
Objects.requireNonNull(action);
return s.tryAdvance(entryConsumer(action));
}
#Override
public void forEachRemaining(Consumer<? super Entry<K, V>> action) {
Objects.requireNonNull(action);
s.forEachRemaining(entryConsumer(action));
}
#Override
public Spliterator<Entry<K, V>> trySplit() {
Spliterator<Entry<K, V>> split = s.trySplit();
return split == null
? null
: new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntrySetSpliterator<>(split);
}
#Override
public long estimateSize() {
return s.estimateSize();
}
#Override
public long getExactSizeIfKnown() {
return s.getExactSizeIfKnown();
}
#Override
public int characteristics() {
return s.characteristics();
}
#Override
public boolean hasCharacteristics(int characteristics) {
return s.hasCharacteristics(characteristics);
}
#Override
public Comparator<? super Entry<K, V>> getComparator() {
return s.getComparator();
}
}
#SuppressWarnings("unchecked")
public Spliterator<Entry<K,V>> spliterator() {
return new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntrySetSpliterator<>(
(Spliterator<Map.Entry<K, V>>) c.spliterator());
}
#Override
public Stream<Entry<K,V>> stream() {
return StreamSupport.stream(spliterator(), false);
}
#Override
public Stream<Entry<K,V>> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
public Iterator<Map.Entry<K,V>> iterator() {
return new Iterator<Map.Entry<K,V>>() {
private final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
public boolean hasNext() {
return i.hasNext();
}
public Map.Entry<K,V> next() {
return new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntry<>(i.next());
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
#SuppressWarnings("unchecked")
public Object[] toArray() {
Object[] a = c.toArray();
for (int i=0; i<a.length; i++)
a[i] = new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)a[i]);
return a;
}
#SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
// We don't pass a to c.toArray, to avoid window of
// vulnerability wherein an unscrupulous multithreaded client
// could get his hands on raw (unwrapped) Entries from c.
Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
for (int i=0; i<arr.length; i++)
arr[i] = new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntry<>((Map.Entry<? extends K, ? extends V>)arr[i]);
if (arr.length > a.length)
return (T[])arr;
System.arraycopy(arr, 0, a, 0, arr.length);
if (a.length > arr.length)
a[arr.length] = null;
return a;
}
/**
* This method is overridden to protect the backing set against
* an object with a nefarious equals function that senses
* that the equality-candidate is Map.Entry and calls its
* setValue method.
*/
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
return c.contains(
new UnmodifiableKeySetMap.UnmodifiableEntrySet.UnmodifiableEntry<>((Map.Entry<?,?>) o));
}
/**
* The next two methods are overridden to protect against
* an unscrupulous List whose contains(Object o) method senses
* when o is a Map.Entry, and calls o.setValue.
*/
public boolean containsAll(Collection<?> coll) {
for (Object e : coll) {
if (!contains(e)) // Invokes safe contains() above
return false;
}
return true;
}
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Set<?> s = (Set<?>) o;
if (s.size() != c.size())
return false;
return containsAll(s); // Invokes safe containsAll() above
}
/**
* This "wrapper class" serves two purposes: it prevents
* the client from modifying the backing Map, by short-circuiting
* the setValue method, and it protects the backing Map against
* an ill-behaved Map.Entry that attempts to modify another
* Map Entry when asked to perform an equality check.
*/
private static class UnmodifiableEntry<K,V> implements Map.Entry<K,V> {
private Map.Entry<? extends K, ? extends V> e;
UnmodifiableEntry(Map.Entry<? extends K, ? extends V> e)
{this.e = Objects.requireNonNull(e);}
public K getKey() {return e.getKey();}
public V getValue() {return e.getValue();}
public V setValue(V value) {
throw new UnsupportedOperationException();
}
public int hashCode() {return e.hashCode();}
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> t = (Map.Entry<?,?>)o;
return eq(e.getKey(), t.getKey()) &&
eq(e.getValue(), t.getValue());
}
public String toString() {return e.toString();}
}
}
/**
* Returns true if the specified arguments are equal, or both null.
*
* NB: Do not replace with Object.equals until JDK-8015417 is resolved.
*/
static boolean eq(Object o1, Object o2) {
return o1==null ? o2==null : o1.equals(o2);
}
}
I know this isn't strictly what was asked in the question, but I think this approach is worth considering.
Use Google Guava's ImmutableMap and make your value type mutable- with a wrapper type if necessary.
Before moving on, it's important to understand this: immutability at the map level only means you can't re-assign objects. There's nothing stopping you from calling mutator methods on the objects already in the map. With this insight, the above approach might be obvious, but let me explain via an example.
For me, the value type was AmtomicInteger- already perfectly mutable in exactly the right way I needed, so I didn't need to change anything. However, in general, let's say you have a type T, and you want a partially mutable map for this type. Well, you can almost do this via a mutable map whose values are wrapper types for that class. Here's a really basic wrapper type, which you might want to enhance with some encapsulation:
public class Wrapper<T>{
public T value;
Wrapper(T t){value = t;}
}
Then you simply create a regular ImmutableMap in the normal way, except fill it with objects of Wrapper instead of objects of T. When using the values, you need to unbox them from the wrapper.
Again, I know this isn't what was asked, and unboxing from a wrapper might be too painful for some use cases, but I'd imagine this would work in a lot of cases. Certainly for me, it helped me realise that I already had a mutable type that was basically a wrapper for an int, and so the ImmmutableMap was fine.
1) The proxy
I would reduce the scope of your SemiMutableMap to something like
interface ISemiMutableMap<U, V> {
V get(U key);
V set(U key, V value) throws Exception; //create your own maybe ?
}
This will reduce the possibilities of access but give you the full control of it.
And then implements it simply like a proxy
public class SemiMutableMap<U, V> implements ISemiMutableMap<U,V>{
private Map<U, V> map;
public SemiMutableMap(Map<U, V> map){ //get the predefine maps
this.map = map;
}
public V get(U key){
return map.get(U);
}
public V set(U key, V value) throws Exception{
if(!map.containsKey(key)){
throw new Exception();
}
return map.put(key,value);
}
}
And you can add the methods you like to it off course.
Note that this is not complety true, The constructor should clone the map instead of using the same reference but I am a bit lazy ;) and I've writen this without an IDE
2) The implementation
Nothing prevent you to simply get the code of the UnmodifiableMap from the Collections and adapt it to your needs. From this, you will see it is quite simple to create your own implementation to your need.
Trust me, this class as been tested and reviewed ;)
You will need to adapt put to be able to update an existing value (same code as above) and UnmodifiableEntry.setValue to accept an update from the entry set.
I believe you want to do something like this.
public class UnmodifiableKeyMap{
static enum MYKeySet {KEY1, KEY2, KEY3, KEY4};
private Map myUnmodifiableHashMap = new HashMap();
public boolean containsKey(Object key) {
return this.containsKey(key);
}
public Object get(Object key) {
if(this.containsKey(key)){
return this.myUnmodifiableHashMap.get(key);
}else {
return null;
}
}
public Object put(Object key, Object value) throws Exception {
if(this.containsKey(key)){
this.myUnmodifiableHashMap.put(key, value);
}
throw new Exception("UnsupportedOperationException");
}
public Set keySet() {
Set mySet = new HashSet(Arrays.asList(MYKeySet.values()));
return mySet;
}
public Collection values() {
return this.myUnmodifiableHashMap.values();
}
}

How could i get Class<? extends List<AlarmRule>> instatnce?

I need to get Class< ? extends List < AlarmRule > > instance.
This is my code:
public static BoundedMatcher<Object, List<AlarmRule>> setBind() {
Class<? extends List<AlarmRule>> clazz = null; // I need to give clazz a value,but i don't know how.
return new BoundedMatcher<Object, List<AlarmRule>>(clazz) {
#Override
public void describeTo(Description description) {
description.appendText("with item content: ");
}
#Override
protected boolean matchesSafely(List<AlarmRule> list) {
return list.stream().anyMatch(alarmRule -> test_reminder_corn.equals(alarmRule.cron));
}
};
}
Thanks for any help!
write like this
public static BoundedMatcher<Object, List> setBind() {
return new BoundedMatcher<Object, List>(List.class) {
#Override
public void describeTo(Description description) {
description.appendText("with item content: ");
}
#Override
protected boolean matchesSafely(List list) {
// convert every object in list to AlarmRule
return false;
}
};
}
In your case you need to pass List.class in the constructor.
However, because of java type erasure, any List may be passed to your matcher so you need to add additional code to ensure your list actually contains AlarmRule objects or you will get a ClassCastException at runtime.

Is it possible to nest hazelcast IMaps? And whick side effects can I expect? Is it a good Idea anyway?

I am just wondering if it is possible to nest IMaps. The quick and simple way says "no".
#Test
public void nest(){
HazelcastInstance instance = Hazelcast.newHazelcastInstance();
IMap<Object, Object> foo = instance.getMap("foo");
IMap<Object, Object> bar = instance.getMap("bar");
bar.lock("bar key");
bar.set("bar key", "mmmmm");
bar.unlock("bar key");
foo.lock("foo key");
foo.set("foo key", bar);
foo.unlock("foo key");
System.out.println(foo);
}
Results in:
com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class com.hazelcast.map.proxy.MapProxyImpl
at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:215)
at
But I mean at the end of the day we just need to know the nested maps name right? So I did a quick and dirty shot:
#Test
public void nest(){
HazelcastInstance instance = Hazelcast.newHazelcastInstance();
IMap<Object, Object> foo = instance.getMap("foo");
IMap<Object, Object> bar = instance.getMap("bar");
bar.lock("bar key");
bar.set("bar key", "mmmmm");
bar.unlock("bar key");
foo.lock("foo key");
foo.set("foo key", new NestedIMap("bar"));
foo.unlock("foo key");
for (Object ky : foo.keySet()) {
Object o = foo.get(ky);
if (o instanceof NestedIMap) {
NestedIMap bar1 = (NestedIMap) o;
bar1.setInstance(instance);
System.out.println("nested map");
for (Object ky2 : bar1.keySet()) {
System.out.println(bar1.get(ky2));
}
} else {
System.out.println(o);
}
}
}
public static class NestedIMap<K, V> implements Map<K, V>, Serializable {
private final String name;
private transient HazelcastInstance instance = null;
private transient IMap cache = null;
public NestedIMap(String name) {
this.name = name;
}
public void setInstance(HazelcastInstance instance) {
this.instance = instance;
}
public IMap<K,V> getIMap() {
return cache != null ? cache : (cache = instance.getMap(name));
}
#Override
public int size() {
return getIMap().size();
}
#Override
public boolean isEmpty() {
return getIMap().isEmpty();
}
#Override
public boolean containsKey(Object key) {
return getIMap().containsKey(key);
}
#Override
public boolean containsValue(Object value) {
return getIMap().containsValue(value);
}
#Override
public V get(Object key) {
return getIMap().get(key);
}
#Override
public V put(K key, V value) {
return getIMap().put(key,value);
}
#Override
public V remove(Object key) {
return getIMap().remove(key);
}
#Override
public void putAll(Map<? extends K, ? extends V> m) {
getIMap().putAll(m);
}
#Override
public void clear() {
getIMap().clear();
}
#Override
public Set<K> keySet() {
return getIMap().keySet();
}
#Override
public Collection<V> values() {
return getIMap().values();
}
#Override
public Set<Entry<K, V>> entrySet() {
return getIMap().entrySet();
}
#Override
public String toString() {
return getIMap().toString();
}
}
Soo ... just because this code is running I am not sure if this is a good idea specially if I use this in a distributed cluster system. Do anyone know which side effects this will have?
It might be possible (from serialization side) but I wouldn't recommend it to be done.

How to implement a generic wrapper for a ResultSet-like API?

I have an third-party RPC-API that provides an interface similar to that of java.sql.ResultSet (for reading values) and java.sql.PreparedStatement (for writing values). Assume it looks something like this:
public interface RemoteDeviceProxy {
public void setBoolean(Boolean value);
public void setInteger(Integer value);
// ...
public Boolean getBoolean();
public Integer getInteger();
// ...
}
I want to write a wrapper for this API that uses generics to create instances of specific types:
public class <T> RemoteVariable {
private final RemoteDeviceProxy wrappedDevice;
public RemoteVariable(RemoteDeviceProxy wrappedDevice) {
this.wrappedDevice = wrappedDevice;
}
public T get() {
// should call wrappedDevice.getBoolean() if T is Boolean, etc.
// how to implement?
}
public void set(T newValue) {
// should call wrappedDevice.setBoolean(newValue) if T is Boolean, etc.
// implement using instanceof
}
}
How can I implement the getter in my generic wrapper? I have found this answer which explains a similar scenario in depth, but I am not able to transfer this to my problem. Specifically, when I write this:
public T get() {
Type[] actualTypeArguments = ((ParameterizedType) getClass())
.getActualTypeArguments();
}
I get a compiler error saying I cannot cast to ParameterizedType, and I do not understand why. Can anyone explain how to achieve this?
Here is one way:
public class <T> RemoteVariable {
private final RemoteDeviceProxy wrappedDevice;
private final Class<T> clazz;
public RemoteVariable(RemoteDeviceProxy wrappedDevice, Class<T> clazz) {
this.wrappedDevice = wrappedDevice;
this.clazz = clazz;
}
public T get() {
if(clazz == Boolean.class){return clazz.cast(wrappedDevice.getBoolean());}
else if(clazz == Integer.class){return clazz.cast(wrappedDevice.getInteger());}
// ...
}
// ...
}
I thought over this quite a while and finally came up with a different approach:
First I added a getter to you RemoteVariable class:
protected RemoteDeviceProxy getWrappedProxy() {
return wrappedProxy;
}
Second I created a builder interface that will be used by a factory later:
public interface RemoteVariableBuilder {
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy);
}
Then I created non generic sub classes for Boolean...
public class RemoteBooleanVariable extends RemoteVariable<Boolean> implements RemoteVariableBuilder {
public RemoteBooleanVariable(RemoteDeviceProxy wrappedProxy) {
super(wrappedProxy);
}
#SuppressWarnings("unchecked")
#Override
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
return (RemoteVariable<T>) new RemoteBooleanVariable(wrappedProxy);
}
#Override
public Boolean get() {
return getWrappedProxy().getBoolean();
}
#Override
public void set(Boolean value) {
getWrappedProxy().setBoolean(value);
}
}
... and Integer ...
public class RemoteIntegerBuilder extends RemoteVariable<Integer> implements RemoteVariableBuilder {
public RemoteIntegerBuilder(RemoteDeviceProxy wrappedProxy) {
super(wrappedProxy);
}
#SuppressWarnings("unchecked")
#Override
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
return (RemoteVariable<T>) new RemoteIntegerBuilder(wrappedProxy);
}
#Override
public Integer get() {
return getWrappedProxy().getInteger();
}
#Override
public void set(Integer value) {
getWrappedProxy().setInteger(value);
}
}
actually eclipse created most of the code once it knew base class and interface.
The final step was to create a factory
public class RemoteVariableFactory {
private static final Map<String, RemoteVariableBuilder> BUILDERS = new HashMap<>();
static {
BUILDERS.put(Boolean.class.getName(), new RemoteBooleanVariable(null));
BUILDERS.put(Integer.class.getName(), new RemoteIntegerBuilder(null));
// add more builders here
}
public static <T> RemoteVariable<T> getRemoteVariable(RemoteDeviceProxy wrappedProxy, Class<T> typeClass) {
RemoteVariableBuilder remoteVariableBuilder = BUILDERS.get(typeClass.getName());
if (remoteVariableBuilder == null) {
return null; // or throw an exception whichever is better in your case
}
return remoteVariableBuilder.buildNewVariable(wrappedProxy);
}
}
Now we are ready to create new RemoteVariables...
RemoteVariable<Boolean> var1 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Boolean.class);
RemoteVariable<Integer> var2 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Integer.class);
To conclude this let's do a quick comparison to the answer of Eng.Fouad:
Disadvantage:
you need to create a new class for every datatype you provide
Advantage:
you only have to add one line to the static block of the factory and not two new if blocks to the getter and setter in RemoteVariable
get and set do not have to work through the if-else-blocks every time

Categories

Resources