I still have a question about Enumerations. Here's a quick sketch of the situation.
I have a class Backpack that has a Hashmap content with as keys a variable of type long, and as value an ArrayList with Items.
I have to write an Enumeration that iterates over the content of a Backpack. But here's the catch: in a Backpack, there can also be another Backpack. And the Enumeration should also be able to iterate over the content of a backpack that is in the backpack. (I hope you can follow, I'm not really good at explaining..)
Here is the code I have:
public Enumeration<Object> getEnumeration() {
return new Enumeration<Object>() {
private int itemsDone = 0;
//I make a new array with all the values of the HashMap, so I can use
//them in nextElement()
Collection<Long> keysCollection = getContent().keySet();
Long [] keys = keysCollection.toArray(new Long[keysCollection.size()]);
public boolean hasMoreElements() {
if(itemsDone < getContent().size()) {
return true;
}else {
return false;
}
}
public Object nextElement() {
ArrayList<Item> temporaryList= getContent().get(keys[itemsDone]);
for(int i = 0; i < temporaryList.size(); i++) {
if(temporaryList.get(i) instanceof Backpack) {
return temporaryList.get(i).getEnumeration();
}else {
return getContent().get(keys[itemsDone++]);
}
}
}
};
Will this code work decently? It's just the "return temporaryList.get(i).getEnumeration();" I'm worried about. Will the users still be able to use just the hasMoreElemens() and nextElement() like he would normally do?
Any help is appreciated,
Harm De Weirdt
You need to create a Stack<Enumeration<Object>>. When you see another Backpack, you push a new Enumeration on that element into the Stack. You always nextElement() from the top of the stack. If the top element is empty, you pop it off. Repeat until the Stack.isEmpty().
Another perhaps simpler technique (depending on how comfortable you are with recursion) is to use "inner" enumerations, which itself can have inner enumerations. Here's a code sample using Iterator on Object[]. It recursively iterates into any nested Object[].
public class RecursiveIterator implements Iterator<Object> {
final Object[] arr;
int index = 0;
Iterator<Object> inner;
RecursiveIterator(Object[] arr) {
this.arr = arr;
}
#Override public boolean hasNext() {
while (true) {
if (inner != null) {
if (inner.hasNext()) {
return true;
} else {
inner = null;
index++;
}
}
if (index == arr.length) return false;
if (arr[index] instanceof Object[]) {
inner = new RecursiveIterator((Object[]) arr[index]);
} else {
return true;
}
}
}
#Override public Object next() {
if (!hasNext()) throw new NoSuchElementException();
return (inner != null) ? inner.next() : arr[index++];
}
#Override public void remove() {
throw new UnsupportedOperationException();
}
}
Here's a test harness:
static void dump(Object[] arr) {
Iterator<Object> iter = new RecursiveIterator(arr);
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
System.out.println("(done)");
}
public static void main(String[] args) throws FileNotFoundException {
dump(new Object[] {
1,
2,
new Object[] {
3,
new Object[] { 4 },
5,
},
6,
new Object[] {},
7,
});
dump(new Object[] {
new Object[] {},
new Object[] {
new Object[] {
new Object[] {},
},
},
new Object[] {},
new Object[] { null },
});
}
This prints:
1 2 3 4 5 6 7 (done)
null (done)
If it was for practical purposes and not homework, I would use the Iterator interface instead of the old Enumeration. For iterators you have some nice utilities in the apache collections project.
Secondly, your solution seems to have a bug. The method nextElement() should return the elements themselves, but the line return temporaryList.get(i).getEnumeration() returns an Enumeration object instead.
--EDIT--
polygenelubricants suggested a nice, elegant solution. I thought of something else. You can implement a generic ChainEnumeration class (implements Enumeration), that receives a list of Enumerations and allows enumerating the underlying items. In your tree structure, return a simple enumeration with one item for leafs, and a chain enumeration of inner nodes.
The implementation of ChainEnumeration is simple: it manages a list of iterators, plus a reference to the current active iterator, where items are taken from.
Related
I'm new in Java and I want to add a list into a BinarySearchTree with an Integer as a Key and a List as value.
So I need every element of a list that I want to add and add to the BST.
I'm using BST because I need to sort it with the key.
In the class Group I have a method called getNumber() that return the number os elements in the that group and the key will be the number of elements of a Group.
Right now I have this and I don't know how to continue. groups.iterator() is just to iterate every group of a list.
orderedGroups is a BinarySearchTree <Integer, List<Group>>().
EDIT:
I have this.
public Iterator<Entry<Integer, List<Group>>> listWarriors() throws NoGroupsException {
if(!isThereGroup())
throw new NoGroupsException();
Iterator<Entry<String, Group>> it = groups.iterator();
List<Group> listGroup = new DoublyLinkedList<Group>();
int j = 0;
while(it.hasNext()) {
listGroup.add(j, it.next().getValue());
j++;
}
for(int i = 0; i<j; i++) {
List<Group> list = orderedGroups.find(listGroup.get(i).getNumber());
if(list == null) {
list = new DoublyLinkedList<Group>();
list.addFirst(listGroup.get(i));
orderedGroups.insert(-(listGroup.get(i).getNumber()), list);
}
else {
if(list.equals(listGroup.get(i))) {
list.addFirst(listGroup.get(i));
}
}
}
return orderedGroups.iterator();
}
OrderedDictionary > orderedGroups = new BinarySearchTree>();
And a group is added by doing this.
public void addGroup(String idGrupo, String nome) throws GroupAlreadyExistsException {
if(searchGroup(idGrupo))
throw new GroupAlreadyExistsException();
group = new GroupClass(idGrupo, nome);
groups.insert(idGrupo.toLowerCase(), group);
}
I have all these in a Class called System.
It looks like you think you have to roll your own iterator in order to enumerate your list. Not necessary.
I can't tell exactly what you are trying to do here, but maybe the below will help, which just demonstrates how to iterate a list.
void addListToGroup(List<Foo> myList, List<group> myGroups) {
for (Foo foo : myList) {
Object value=myList.someFunction();
Group newGroup = new Group(value);
myGroups.add(newGroup);
}
}
I'm not sure I understand fully what you're trying to do, and why you're not using LinkedList and TreeMap, but I see a few issues in your code:
your for loop makes i start at 1 whereas list indices start at 0,
building listGroup seems useless: you could directly build orderedGroups
orderedGroups is not modified in your code (orderedGroupsByC is though)
UPDATE:
What if you did this:
Iterator<Entry<String, Group>> it = groups.iterator();
while (it.hasNext()) {
Group group = it.next();
List<Group> list = orderedGroups.find(group.getNumber());
if (list == null) {
list = new DoublyLinkedList<Group>();
list.addFirst(group);
orderedGroups.insert(group.getNumber(), list);
} else {
list.addFirst(group);
}
}
I have an object list that retrieves multiple values from a database, like so:
List<Object> listRequest = daoManager.getLaptopsForRequest(BigInteger.valueOf(itemTransItem.getAssetType().getId()), BigInteger.valueOf(approverId));
The result of which looks like this (printed out on the console, via for each):
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=1, asset_id=1, status=1, thru_dt=null}
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=2, asset_id=2, status=1, thru_dt=null}
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=3, asset_id=3, status=1, thru_dt=null}
What's the quickest and/or most efficient way to get only the object where asset_id = 2, or an array of asset_id (1 and 2), and putting the results in another array?
I contemplated casting each object as a string, and then turning each string into an array (split by the comma), and then turning each item of the array into a further array (or a hashmap) by using the =, but that seems like a long, long, complex way of nested for loops that might fail (see comparing array of assets).
Perhaps there's another quicker / less complex way to do this that I'm missing? Any suggestions? Thanks.
EDIT: For reference, here's the getLaptopsForRequest function:
public List getLaptopsForRequest(BigInteger asset_type_id, BigInteger party_id){
SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery(laptopsForRequestSql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List forRequest = query.setBigInteger(0, asset_type_id).setBigInteger(1, party_id).list();
return forRequest;
}
It returns a list of the results of the query. As this code has been in place, I'm not allowed to edit it.
A quick and dirty solution would be to match each item against regex ^.*asset_id=([0-9]+).*$.
If what you're getting from that method is indeed a list of Strings containing those JSONs, you could create a model class and use a JSON serializer like GSON or Jackson to read the strings into Java objects, and then you could work with them.
What you are trying to do basically is to filter a list of objects. You could implement the Filter Pattern writing your own Iterator for the list.
Just extends this class to implement your own filter.
public abstract class Filter<T> {
public abstract boolean passes(T object);
public Iterator<T> filter(Iterator<T> iterator) {
return new FilterIterator(iterator);
}
public Iterable<T> filter(Iterable<T> iterable) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return filter(iterable.iterator());
}
};
}
private class FilterIterator implements Iterator<T> {
private Iterator<T> iterator;
private T next;
private FilterIterator(Iterator<T> iterator) {
this.iterator = iterator;
toNext();
}
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null)
throw new NoSuchElementException();
T returnValue = next;
toNext();
return returnValue;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void toNext() {
next = null;
while (iterator.hasNext()) {
T item = iterator.next();
if (item != null && passes(item)) {
next = item;
break;
}
}
}
}
}
and then use it in this way:
List<MyObject> newList = new ArrayList<MyObject>();
for(MyObject obj : filter.filter(listObjs) ){
newList.add(obj);
}
Assuming your objects have getter et setter methods.
Only the object where asset_id = "2", asset_id here being a string
listRequest.stream().filter(e -> e.getAssetId() == "2" ).toArray();
I should write a method that returns all cousins of the Person as an array of Person objects. A Person object has mother, father, children[] etc. as its instance variables and I should use this method to find all siblings of a Person's uncles and aunts then their children.
public Person[] allSiblings(){
int a = this.mother.children.length - 1;
Person[] siblings = new Person[a];
for(i=0; i<siblings.length; i++){
if(this.mother.children[i] == this)
continue;
else{
siblings[i] = this.mother.children[i];
}
}
return siblings;
}
So how can I merge these children arrays and return as one Person array in allCousins() method. I know it would be easier to use ArrayList but we are not allowed.
Thanks in advance.
Have a look at
How can I concatenate two arrays in Java?
There are some methods on how to do that. The trick is to either use a ready made function (which you probably are not allowed if Lists are forbidden) or to create a new Array with the sum of the two original Arrays as length.
The link mentioned by JoshOvi is good one. If you want to create your own implementation, consider ArrayUtils as reference -
public Object[] mergeArray(final Object[] arr1, final Object[] arr2) {
if (arr1 == null) {
return clone(arr2);
}
else if (arr2 == null) {
return clone(arr1);
}
Object[] mergedArray = new Object[arr1.length+arr2.length];
System.arraycopy(arr1, 0, mergedArray, 0, arr1.length);
System.arraycopy(arr2, 0, mergedArray, arr1.length, arr2.length);
return mergedArray;
}
public Object[] clone(Object[] array) {
if (array == null) {
return null;
}
return (Object[]) array.clone();
}
ArrayList searchList = new ArrayList();
ArrayList words=(ArrayList) request.getSession().getAttribute("words");
words.add("one");
words.add("twenty one");
words.add("thirty one");
words.add("two");
words.add("twenty two");
words.add("thirty two");
words.add("three");
words.add("twenty three");
words.add("thirty three");'
If I have this arraylist and I want to search all the strings containing one(i.e. one,twenty one and thirty one), what logic should I use? Means how should I do that?
for (String item : searchList) {
if (item.contains("one") {
// Do something. Like adding the result to a different list.
// If you need the index from the original list, you a for instead of a for each
}
}
//iterate through words
for(String str : list){
//check if word contains the key
if(str.contains(key)){
//add its reference to another resultant list
result.add(str);
}
}
for (String word : words) {
if (word.contains("one")) {
//we have a match
}
}
Of course you have to loop thru the elements. Look for ways to loop thru an ArrayList: that can be indexed or with the
for (x : collect)
notation.
In the loop you have to do some pattern matching. Read String Java API doc for a method.
(Give'em some think food ...)
You could solve this using iterators if the condition will be more complex
public interface IPredicate<T> {
boolean check(T t);
}
public class PredicatIterable<T> implements Iterable<T> {
private final Iterator<T> iterator;
private final IPredicate<T> predicate;
public PredicatIterable(Iterable<T> iterable, IPredicate<T> predicate) {
this.iterator = iterable.iterator();
this.predicate = predicate;
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
T current;
#Override
public boolean hasNext() {
if(iterator.hasNext()) {
T next = iterator.next();
if(predicate.check(next)) {
current = next;
return true;
}
current = null;
}
return false;
}
#Override
public T next() {
return current;
}
#Override
public void remove() {
throw new RuntimeException("Invalid useage of method");
}
};
}
}
To validate more the single predicate you can create also method that is responsible for conuntion or alternative of two IPredicate argument.
In general, when searching an item in a List, the best solution is to sort your List first using Collections.sort() method. Then using the Collections.binarySearch() method, find your element.
In this case your elements are String type that are Comparable and can be sorted alphabetically otherwise you needed to implement Comparable interface for your element class type.
I'm migrating a piece of code to make use of generics. One argument for doing so is that the for loop is much cleaner than keeping track of indexes, or using an explicit iterator.
In about half the cases, the list (an ArrayList) is being iterated in reverse order by using an index today.
Can someone suggest a cleaner way of doing this (since I dislike the indexed for loop when working with collections), though it does work?
for (int i = nodes.size() - 1; i >= 0; i--) {
final Node each = (Node) nodes.get(i);
...
}
Note: I can't add any new dependencies outside the JDK.
Try this:
// Substitute appropriate type.
ArrayList<...> a = new ArrayList<...>();
// Add elements to list.
// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());
// Iterate in reverse.
while(li.hasPrevious()) {
System.out.println(li.previous());
}
Guava offers Lists#reverse(List) and ImmutableList#reverse(). As in most cases for Guava, the former delegates to the latter if the argument is an ImmutableList, so you can use the former in all cases. These do not create new copies of the list but just "reversed views" of it.
Example
List reversed = ImmutableList.copyOf(myList).reverse();
I don't think it's possible using the for loop syntax. The only thing I can suggest is to do something like:
Collections.reverse(list);
for (Object o : list) {
...
}
... but I wouldn't say this is "cleaner" given that it's going to be less efficient.
Option 1: Have you thought about reversing the List with Collections#reverse() and then using foreach?
Of course, you may also want to refactor your code such that the list is ordered correctly so you don't have to reverse it, which uses extra space/time.
EDIT:
Option 2: Alternatively, could you use a Deque instead of an ArrayList? It will allow you to iterate forwards and backwards
EDIT:
Option 3: As others have suggested, you could write an Iterator that will go through the list in reverse, here is an example:
import java.util.Iterator;
import java.util.List;
public class ReverseIterator<T> implements Iterator<T>, Iterable<T> {
private final List<T> list;
private int position;
public ReverseIterator(List<T> list) {
this.list = list;
this.position = list.size() - 1;
}
#Override
public Iterator<T> iterator() {
return this;
}
#Override
public boolean hasNext() {
return position >= 0;
}
#Override
public T next() {
return list.get(position--);
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
for (String s : new ReverseIterator<String>(list)) {
System.out.println(s);
}
You could use the concrete class LinkedList instead of the general interface List. Then you have a descendingIterator for iterating with the reverse direction.
LinkedList<String > linkedList;
for( Iterator<String > it = linkedList.descendingIterator(); it.hasNext(); ) {
String text = it.next();
}
Don't know why there is no descendingIterator with ArrayList...
This is an old question, but it's lacking a java8-friendly answer. Here are some ways of reverse-iterating the list, with the help of the Streaming API:
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 3, 3, 7, 5));
list.stream().forEach(System.out::println); // 1 3 3 7 5
int size = list.size();
ListIterator<Integer> it = list.listIterator(size);
Stream.generate(it::previous).limit(size)
.forEach(System.out::println); // 5 7 3 3 1
ListIterator<Integer> it2 = list.listIterator(size);
Stream.iterate(it2.previous(), i -> it2.previous()).limit(size)
.forEach(System.out::println); // 5 7 3 3 1
// If list is RandomAccess (i.e. an ArrayList)
IntStream.range(0, size).map(i -> size - i - 1).map(list::get)
.forEach(System.out::println); // 5 7 3 3 1
// If list is RandomAccess (i.e. an ArrayList), less efficient due to sorting
IntStream.range(0, size).boxed().sorted(Comparator.reverseOrder())
.map(list::get).forEach(System.out::println); // 5 7 3 3 1
Here is an (untested) implementation of a ReverseIterable. When iterator() is called it creates and returns a private ReverseIterator implementation, which simply maps calls to hasNext() to hasPrevious() and calls to next() are mapped to previous(). It means you could iterate over an ArrayList in reverse as follows:
ArrayList<String> l = ...
for (String s : new ReverseIterable(l)) {
System.err.println(s);
}
Class Definition
public class ReverseIterable<T> implements Iterable<T> {
private static class ReverseIterator<T> implements Iterator {
private final ListIterator<T> it;
public boolean hasNext() {
return it.hasPrevious();
}
public T next() {
return it.previous();
}
public void remove() {
it.remove();
}
}
private final ArrayList<T> l;
public ReverseIterable(ArrayList<T> l) {
this.l = l;
}
public Iterator<T> iterator() {
return new ReverseIterator(l.listIterator(l.size()));
}
}
If the lists are fairly small so that performance is not a real issue, one can use the reverse-metod of the Lists-class in Google Guava. Yields pretty for-each-code, and the original list stays the same. Also, the reversed list is backed by the original list, so any change to the original list will be reflected in the reversed one.
import com.google.common.collect.Lists;
[...]
final List<String> myList = Lists.newArrayList("one", "two", "three");
final List<String> myReverseList = Lists.reverse(myList);
System.out.println(myList);
System.out.println(myReverseList);
myList.add("four");
System.out.println(myList);
System.out.println(myReverseList);
Yields the following result:
[one, two, three]
[three, two, one]
[one, two, three, four]
[four, three, two, one]
Which means that reverse iteration of myList can be written as:
for (final String someString : Lists.reverse(myList)) {
//do something
}
You could use ReverseListIterator from Apache Commons-Collections:
https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/iterators/ReverseListIterator.html
Very simple Example:
List<String> list = new ArrayList<String>();
list.add("ravi");
list.add("kant");
list.add("soni");
// Iterate to disply : result will be as --- ravi kant soni
for (String name : list) {
...
}
//Now call this method
Collections.reverse(list);
// iterate and print index wise : result will be as --- soni kant ravi
for (String name : list) {
...
}
To have code which looks like this:
List<Item> items;
...
for (Item item : In.reverse(items))
{
...
}
Put this code into a file called "In.java":
import java.util.*;
public enum In {;
public static final <T> Iterable<T> reverse(final List<T> list) {
return new ListReverseIterable<T>(list);
}
class ListReverseIterable<T> implements Iterable<T> {
private final List<T> mList;
public ListReverseIterable(final List<T> list) {
mList = list;
}
public Iterator<T> iterator() {
return new Iterator<T>() {
final ListIterator<T> it = mList.listIterator(mList.size());
public boolean hasNext() {
return it.hasPrevious();
}
public T next() {
return it.previous();
}
public void remove() {
it.remove();
}
};
}
}
}
Create a custom reverseIterable.
Also found google collections reverse method.
How about using DeQue:
var queue = new ArrayDeque<>(list);
while (!queue.isEmpty()) {
var first = reversed ? queue.removeLast() : queue.removeFirst();
var second = reversed ? queue.peekLast() : queue.peekFirst();
if (second != null) {
//your code goes here
}
}
As has been suggested at least twice, you can use descendingIterator with a Deque, in particular with a LinkedList. If you want to use the for-each loop (i.e., have an Iterable), you can construct and use a wraper like this:
import java.util.*;
public class Main {
public static class ReverseIterating<T> implements Iterable<T> {
private final LinkedList<T> list;
public ReverseIterating(LinkedList<T> list) {
this.list = list;
}
#Override
public Iterator<T> iterator() {
return list.descendingIterator();
}
}
public static void main(String... args) {
LinkedList<String> list = new LinkedList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
for (String s : new ReverseIterating<String>(list)) {
System.out.println(s);
}
}
}
Valid for Java 9+
List<String> strList = List.of("a", "b", "c", "d", "e");
IntStream.iterate(strList.size() - 1, i -> i >= 0, i -> --i)
.mapToObj(strList::get)
.forEach(System.out::println);
Reason : "Don't know why there is no descendingIterator with ArrayList..."
Since array list doesnot keep the list in the same order as data has been added to list. So, never use Arraylist .
Linked list will keep the data in same order of ADD to list.
So , above in my example, i used ArrayList() in order to make user to twist their mind and make them to workout something from their side.
Instead of this
List<String> list = new ArrayList<String>();
USE:
List<String> list = new LinkedList<String>();
list.add("ravi");
list.add("kant");
list.add("soni");
// Iterate to disply : result will be as --- ravi kant soni
for (String name : list) {
...
}
//Now call this method
Collections.reverse(list);
// iterate and print index wise : result will be as --- soni kant ravi
for (String name : list) {
...
}