I came across a class in our java project that is confusing for me to understand.
It implements the Iterable interface with a type parameter as it's self for that iterable. Could someone shed some light on to what this does and why it would be useful?
public class IndexRequest extends Request implements Cloneable, Iterable<IndexRequest> {
public enum OpType {insert, update};
protected Index index;
protected Type type;
protected boolean incomingAsArray;
protected long timeToLive;
protected String parent;
protected String route;
protected LinkedListMultimap<String, IndexRequest> iterable;
protected String errorMessage;
protected String stackTrace;
protected String warnMessage;
protected OpType opType = OpType.insert;
protected long versionId;
protected JsonNode previousDocument;
protected boolean ignored;
protected String resultCode;
protected int retries = 0;
protected boolean esUpsertFlag = false;
protected String id = UUID.randomUUID().toString();
/**
* Constructor
*/
public IndexRequest() {
super();
logger = LoggerFactory.getLogger(IndexRequest.class);
this.requestJson = JsonNodeFactory.instance.arrayNode();
}
/**
* Constructor
*/
public IndexRequest(String endpointPath, String requestId, String user, JsonNode requestJson, Map<String, String[]> requestParameters) {
super(endpointPath, requestId, user, requestJson, requestParameters);
}
/**
* Initialize our iterable version of this class
*/
protected void initIterable() {
LinkedListMultimap <String, IndexRequest> contents = LinkedListMultimap.create();
if (isArray()) {
ArrayNode docsArray = (ArrayNode) getDocument();
Iterator<JsonNode> docIterator = docsArray.iterator();
while (docIterator.hasNext()) {
IndexRequest is = this.clone(false);
// generate a new id since this is a new wrapper around a particular doc
is.id = UUID.randomUUID().toString();
is.setDocument(docIterator.next());
contents.put(is.getId(), is);
}
iterable = contents;
}
else {
iterable = LinkedListMultimap.create();
iterable.put(getId(), this);
}
}
/**
* Returns an iterator for this index set
* #return Iterator<IndexRequest> An iterator for this index set
*/
public Iterator<IndexRequest> iterator() {
if (iterable == null) {
initIterable();
}
return iterable.values().iterator();
}
}
Thank you in advance.
A class that implements the Iterable can be used with the new for-loop. Here is such an example:
List list = new ArrayList();
for(Object o : list){
//do something o;
}
The Iterable interface has only one method:
public interface Iterable<T> {
public Iterator<T> iterator();
}
It is possible to use our own collection type classes with the new for-loop. To do so, our class must implement the java.lang.Iterable interface. and provide the implementation of iterator method , which you can see in your class is provided here :
/**
* Returns an iterator for this index set
* #return Iterator<IndexRequest> An iterator for this index set
*/
public Iterator<IndexRequest> iterator() {
if (iterable == null) {
initIterable();
}
return iterable.values().iterator();
}
This class looks like it defines a node in a tree of such nodes. Instances hold a map from Strings to other instances of the same class:
protected LinkedListMultimap<String, IndexRequest> iterable;
They also inherit from their parent class some sense of being / holding an array of other instances. When they are iterated, they provide the values from their map or the elements of their array.
Related
I'm getting the results from the database into a List<Map<String, Object>>. The problem the values are not in order, so I thought to cast in a LinkedHashMap, but I get this exception:
javax.ejb.EJBException: java.lang.ClassCastException: class java.util.HashMap cannot be cast to class java.util.LinkedHashMap (java.util.HashMap and java.util.LinkedHashMap are in module java.base of loader 'bootstrap')
The method is this:
protected EntityManager em;
Query q = em.createNativeQuery("select * from City");
NativeQueryImpl nativeQuery = (NativeQueryImpl) q;
nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<LinkedHashMap<String, Object>> r = (List<LinkedHashMap<String, Object>>) nativeQuery.getResultList();
r.stream().forEach(System.out::println);
Does anybody knows how can I print results in order?
Create this class and call it instead of: AliasToEntityMapResultTransformer.INSTANCE
public class MyTransformer extends AliasedTupleSubsetResultTransformer {
public static final MyTransformer INSTANCE = new MyTransformer();
/**
* Disallow instantiation of AliasToEntityMapResultTransformer.
*/
private MyTransformer() {
}
#Override
public Object transformTuple(Object[] tuple, String[] aliases) {
Map result = new LinkedHashMap<>(tuple.length);
for (int i = 0; i < tuple.length; i++) {
String alias = aliases[i];
if (alias != null) {
result.put(alias, tuple[i]);
}
}
return result;
}
#Override
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
return false;
}
/**
* Serialization hook for ensuring singleton uniqueing.
*
* #return The singleton instance : {#link #INSTANCE}
*/
private Object readResolve() {
return INSTANCE;
}
}
addAll at index, iterator set methods
Based on the lectures this week, we implemented ArrayList -- an order-dependent collection that grows as more data is added to it. Overall, it was based on an underlying array. However, two methods were left unimplemented: ArrayList.addAll(int index, Collection<? extends E>) and ArrayListIterator.set(E element). In this problem you are to implement those methods. A suite of test cases is provided. Consulting the documentation for List and ListIterator may be helpful.
You should not need access to any private fields, but based on the presentation in class, the following data and methods have been made protected instead of private so that you may access them:
public class ArrayList<E> extends AbstractList<E> {
protected static final int DEFAULT_CAPACITY = 10;
protected E [] data;
protected int size;
protected int modCount;
protected void ensureCapacity(int requiredCapacity) {
// etc.
}
protected class ArrayListIterator implements ListIterator<E> {
protected int cursor;
protected int priorCursor;
protected int expectedModCount;
protected void checkForComodification() {
// etc.
}
protected void updateAndSynchronizeModeCounts() {
// etc
}
}
Here is the program:
import java.util.Collection;
import java.util.List;
import java.util.Iterator;
import java.util.ListIterator;
/**
* Write a description of class W7Problem here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class W7Problem<E> extends ArrayList<E>
{
// Scaffolding for the problem. Don't touch.
public W7Problem() {
super();
}
// Scaffolding for the problem. Don't touch.
public W7Problem(int initialCapacity) {
super(initialCapacity);
}
/**
* Inserts all the elements of <tt>coll</tt> into this collection at
* the specified location. If both this collection and the parameter
* are the same collection, then the operational behavior is undefined
* (i.e. bad things can happen).
* #param index the location at which to insert
* #param coll the collection from which to draw elements for addition.
* #return true when this collection is modified as a result.
*
* Time complexity: TODO___________
*/
#Override
public boolean addAll(int index, Collection<? extends E> coll) {
// TODO: your code goes here
//throw new UnsupportedOperationException();
//checkBoundInclusive(index);
Iterator<? extends E> itr = coll.iterator();
int csize = coll.size();
modCount++;
if (csize + size > data.length){
ensureCapacity(size + csize);
}
int end = index + csize;
if (size > 0 && index != size){
System.arraycopy(data, index, data, end, size - index);
}
size += csize;
for ( ; index < end; index++){
data[index] = itr.next();
}
return csize > 0;
}
// Scaffolding for the problem. Don't touch.
#Override
public Iterator<E> iterator() {
return listIterator();
}
// Scaffolding for the problem. Don't touch.
#Override
public ListIterator<E> listIterator() {
return listIterator(0);
}
// Scaffolding for the problem. Don't touch.
#Override
public ListIterator<E> listIterator(int index) {
return new W7ProblemIterator(index);
}
private class W7ProblemIterator extends ArrayList<E>.ArrayListIterator {
// Scaffolding for the probmem. Don't touch.
public W7ProblemIterator(int startIndex) {
super(startIndex);
}
/**
* Replaces the last element returned by either <tt>next</tt> or
* <tt>previous</tt>. Cannot be called immediately after <tt>add</tt>
* or <tt>remove</tt>.
* #param obj the object with which to replace the one returned
* earlier.
*
* Time complexity: TODO___________
*/
#Override
public void set(E obj) {
// TODO: Your code goes here
//throw new UnsupportedOperationException();
//throw new UnsupportedOperationException("unsupported");
}
}
}
I have completed the addAll() method without any trouble and passed all of the test cases. My problem is with the set() method. No matter what I try, I cannot pass the last 3 test cases.
Is there any way to find the ListIterator.set() source code?
Any help is appreciated. I'm looking for a point in the right direction in how to write my set() method.
Thank you!
I am implementing an undo/redo function which requires me to use memento pattern.
The flow of the partial program : "...the program then store the previous Vector using Memento Pattern, then the newly created object will be added to the Vector. After that, user may choose a show command to show what is inside the Vector, he can also enter undo command to restore, the undo can be repeated until it is restored to the original state..."
From my research, I know there will be an originator, memento and caretaker.
Here's my caretaker program
public class CareTaker {
private Memento m;
private Stack s;
private Vector v;
// Some of the implementation are not shown
public void create() {
// Some of the implementation are not shown
// Assuming Vector is named "v"
// Passing Vector to memento
m = new Memento(v);
s.add(m);
}
public void undo() {
v = s.pop().restore();
}
}
public class Memento {
private Vector _v;
public Memento(Vector v) {
_v = v;
}
public Vector restore() {
return _v;
}
}
Unfortunately , I failed to identify the "Originator" nor I know which one will be.
Is this code fragment ever a correct Memento pattern if there is no Originator?
The memento pattern is used to save the state of an object without knowing it's internal data structures.
I try to explain it with an Iterator example
public class MementoListIterator<E> implements Iterator<E> {
public static class Memento {
private int savedIndex;
private Memento(MementoListIterator<?> mementoListIterator) {
this.savedIndex = mementoListIterator.index;
}
}
private List<E> elements;
private int index = 0;
public MementoListIterator(List<E> elements) {
this.elements = elements;
}
public Memento save() {
return new Memento(this);
}
public void restore(Memento memento) {
this.index = memento.savedIndex;
}
#Override
public boolean hasNext() {
return this.index < elements.size();
}
#Override
public E next() {
return elements.get(index++);
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not implemented yet");
}
}
A client can now save any state of the iterator without knowing how the iterator internally manages it's state.
public class Main {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C", "D", "E");
MementoListIterator<String> mementoListIterator = new MementoListIterator<String>(
list);
Memento initialState = mementoListIterator.save();
while (mementoListIterator.hasNext()) {
String string = mementoListIterator.next();
System.out.println(string);
}
// Normally we can not re-use the iterator, but
// fortuanatly we saved the initial state.
// restore the initial state and we can use the Iterator again
mementoListIterator.restore(initialState);
while (mementoListIterator.hasNext()) {
String string = mementoListIterator.next();
System.out.println(string);
}
}
}
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.
HashMapList keeps its elements inside a HashMap) and when I call add method this error message will be shown in the concole "Exception in thread "main" java.lang.NullPointerException
public class HashMapList<K, V extends Product> extends AbstractList<Product> {
public V element;
public int index;
Map<Integer, V> map;
public HashMapList() {
super();
new HashMap<Integer, V>();
}
// Override
public void add(int index, V element) {
map.put(new Integer(index), element);
}
}
thanks,I have solved the first problem but when I call add method like==>
HashMapList<Integer, Book> list = new HashMapList<Integer, Book>();
list.add(0, new Book("physics"));
and Book class is==>
public class Book extends Product {
public String name = null;
public Book(String name) {
super(name);
}
}
and Product class is==>
public class Product implements Comparable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name = null;
public Product(String name) {
if (name == null)
throw new NullPointerException();
this.name = name;
}
public String getName() {
return name;
}
// Override
public int compareTo(Object o) {
Product product = (Product) o;
int compare = getName().compareTo(product.name);
return compare;
}
}
And when I want to print this list basically with System.out.println(list);
this sentence will be shown in the concole:[org.bihe.com1112.Book#1fb8ee3, org.bihe.com1112.Book#61de33, org.bihe.com1112.Book#14318bb]
You are not assigning anything to map
public HashMapList() {
super();
map = new HashMap<Integer, V>();
}
whenever you get a null pointer exception look for where you assign a value to the variable to you are using. Here look for anywhere in your code where you say "map = ...".
For your second question, you should really start another thread. It is correctly printing the string representation of your object. Your Book class does not provide a custom overridden toString() method. So it uses the one inherited from Object, which just returns a string made of the full name of the class and the hashCode of the object, which is what you are seeing. You should override the toString() method if you want to see something different.
look at your constructor.
new HashMap<Integer, V>();
should be
map = new HashMap<Integer, V>();