How can I make an iterator that never ends? - java

I was just wondering what the easiest way to iterate over a set indefinitely, i.e. when it reaches the end it next(); calls the first object. I'm assuming that this is not an already predefined function in Java, so just looking for the easiest way to implement this in Java.

There's a method in the excellent Google Collections library which does this:
Set<String> names = ...;
Iterable<String> infinite = Iterables.cycle(names);
(I can't recommend the Google Collections library strongly enough. It rocks very hard. I'm biased as I work for Google, but I think pretty much every Googler writing Java would tell you how useful the collections are.)

Iterator it = mylist.iterator();
while (it.hasNext())
{
MyType t = (MyType)it.next();
// do something
if (!it.hasNext())
it = mylist.iterator();
}

Try EndlessIterator from Cactoos:
Iterator<String> names = new EndlessIterator<>("John");
It will always return "John" and will never end.
Also, check EndlessIterable, which implements Iterable and does the same.

If you're making the iterator, in the next method you can have an if condition that checks if there's another object in the list. If there is, then you return that object, if there isn't then you go back to the start of the list and return that object.

This is what I can think of...
iterator = set.getIterator
//other code
if (iterator.hasNext())
//do code here
else
iterator = set.getIterator();

How about ?
List<String> list = // ArraysList
Interator<String> it = null;
while(true) {
it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}

If you don't want to use Guava but still want a reusable solution:
public static class CyclicIterator<E, C extends Collection<E>> implements Iterator<E> {
final private C mElements;
private Iterator<E> mIterator;
public CyclicIterator(C elements) {
mElements = elements;
mIterator = elements.iterator();
}
#Override
public boolean hasNext() {
if (! mIterator.hasNext()) {
mIterator = mElements.iterator();
}
return mIterator.hasNext();
}
#Override
public E next() {
if (! mIterator.hasNext()) {
mIterator = mElements.iterator();
}
return mIterator.next();
}
}
Note: this doesn't support the remove() method but it could easily be added if needed. Also it's not thread safe.

I think what you want never help You can do anything with your iterator that's easy but you must be carefull with any new thing you add im not used with this style but this is what you want though :
if (! It.hasNext() )
{
while ( It.hasPrevious() )
{
It = It.Previous();
}
} else {
It = It.Next();
}
This way is nothing if your really interested you should instead make next pointer of the last to the first always when pushing a new list.

std jdk:
Iterable<String> infinite = Stream.generate(names.stream()).flatMap(e -> e).iterator()

Related

How can I prevent mutation of a list of iterators?

I would like to avoid the mutation of the input list of iterators tests by others. I only want others to run on a deep copy of tests.
How can this be achieved in Java?
Here is an example showing the effect of the mutation on tests. Both of the two parts are sorting the input. But the second part has nothing to be sorted since the mutation from the first part iterated the iterators to the end.
You can run the following example online here:
https://onlinegdb.com/NC4WzLzmt
import java.util.*;
public class ImmutableExample {
public static void main(String[] args) {
System.out.println("sort on demand");
List<Iterator<Integer>> mutableTests = Arrays.asList(
Arrays.asList(1, 2).iterator(),
Arrays.asList(0).iterator(),
Collections.emptyIterator()
);
List<Iterator<Integer>> tests = Collections.unmodifiableList(mutableTests);
MergingIterator mergingIterator = new MergingIterator(tests);
while (mergingIterator.hasNext()) {
System.out.println(mergingIterator.next());
}
System.out.println("sort all at once");
/* uncomment the following will see the same result:*/
// tests = Arrays.asList(
// Arrays.asList(1, 2).iterator(),
// Arrays.asList(0).iterator(),
// Collections.emptyIterator()
// );
MergeKSortedIterators sol = new MergeKSortedIterators();
Iterable<Integer> result = sol.mergeKSortedIterators(tests);
for (Integer num : result) {
System.out.println(num);
}
}
}
class PeekingIterator implements Iterator<Integer>, Comparable<PeekingIterator> {
Iterator<Integer> iterator;
Integer peekedElement;
boolean hasPeeked;
public PeekingIterator(Iterator<Integer> iterator) {
this.iterator = iterator;
}
public boolean hasNext() {
return hasPeeked || iterator.hasNext();
}
public Integer next() {
int nextElem = hasPeeked ? peekedElement : iterator.next();
hasPeeked = false;
return nextElem;
}
public Integer peek() {
peekedElement = hasPeeked ? peekedElement : iterator.next();
hasPeeked = true;
return peekedElement;
}
#Override
public int compareTo(PeekingIterator that) {
return this.peek() - that.peek();
}
}
class MergingIterator implements Iterator<Integer> {
Queue<PeekingIterator> minHeap;
public MergingIterator(List<Iterator<Integer>> iterators) {
// minHeap = new PriorityQueue<>((x, y) -> x.peek().compareTo(y.peek()));
minHeap = new PriorityQueue<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
minHeap.offer(new PeekingIterator(iterator));
}
}
}
public boolean hasNext() {
return !minHeap.isEmpty();
}
public Integer next() {
PeekingIterator nextIter = minHeap.poll();
Integer next = nextIter.next();
if (nextIter.hasNext()) {
minHeap.offer(nextIter);
}
return next;
}
}
class MergeKSortedIterators {
public Iterable<Integer> mergeKSortedIterators(List<Iterator<Integer>> iteratorList) {
List<Integer> result = new ArrayList<>();
if (iteratorList.isEmpty()) {
return result;
}
PriorityQueue<PeekingIterator> pq = new PriorityQueue<>();
for (Iterator<Integer> iterator : iteratorList) {
if (iterator.hasNext()) {
pq.add(new PeekingIterator(iterator));
}
}
while (!pq.isEmpty()) {
PeekingIterator curr = pq.poll();
// result.add(curr.peek());
// cannot use this one as hasNext() checks on `hasPeeked`
result.add(curr.next());
if (curr.hasNext()) {
pq.add(curr);
}
}
return result;
}
}
This question seems to be based on a misunderstanding ... or two.
How can I prevent mutation of a list of iterators?
You need to distinguish between the mutability of a list, and the mutability of the items in the list. I think you are actually asking about the latter. (And as such, the list is not really relevant to the question. As we shall see.)
I would like to avoid the mutation of the input list of iterators tests by others.
Again, you appear to be asking about the list, but I think you actually mean to ask about the iterators.
I only want others to run on a deep copy of tests.
This implies you want the iterators to be immutable.
Here's the problem:
An Iterator is an inherently stateful / mutable object. Indeed, there is no way to implement next() without mutating the iterator object.
Iterator objects are typically not deep copyable. They typically don't support clone() or public constructors, and they typically do not implement Serializable. (Indeed, if they were serializable, the semantics of serialize / deserialize would be problematic.)
So basically, your idea of a list of immutable iterators or a list that (somehow) produces deep copies of iterators is not practical.
You commented:
So List<Iterator<Integer>> tests = Collections.unmodifiableList(mutableTests); cannot produce an unmodifiable list for List<Iterator<Integer>>?
Well, yes it can. But that doesn't solve the problem. You need a list of unmodifiable iterators rather than an unmodifiable list of iterators.
Possible solutions:
You could just recreate the list of iterators from their base collections for each test run.
Use Iterable instead of Iterator. The collection types you are using all implement Iterable, and the third iterator could be created from an empty list.
List<Iterable<Integer>> tests = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(0),
Collections.emptyList()
);
// to use them ...
for (Iterable<Integer> iterable : tests) {
Iterator<Integer> iterator = iterable.iterator();
// etc ...
}
If your iterators could not be recreated (for example, if you were iterating a source that couldn't be created or "rewound"), you could conceivably implement a caching iterator wrapper that remembered all of the elements in the iteration sequence and could either reset to the start of the sequence, or generate a new iterator to replay the sequence. (But that would be overkill here.)

Local storage in a stream Java 8

I want to write a stream method that may need to ignore several concurrent values based on a "lastGoodVersion" but I can't find a way to share the value within the stream. Below is what I'd LIKE to do. Any suggestions on how to accomplish something like this?
[EDIT don't do this, it's not how java streams work]
I don't think this is possible using only Java 8 Streams. A possible solution to what you want to do could however use a helper function which may look something like this:
private static <T> Stream<T> progressiveFilter(Stream<T> stream,
BiPredicate<T, T> predicate) {
List<T> list = stream.collect(Collectors.toList());
List<T> result = new ArrayList<>();
T previousValue = null;
for (T entry : list) {
if (previousValue == null) {
previousValue = entry;
} else {
if (predicate.test(entry, previousValue)) {
result.add(previousValue);
} else {
previousValue = entry;
}
}
}
if(previousValue != null) {
result.add(previousValue);
}
return result.stream();
}
The call you are trying would then look something like this:
progressiveFilter(
allVersionsStream().filter(NSTimestamp::isApproved),
(v, lastCanonicalVersion) -> !v.isEffectiveBefore(relativeDate)
&& v.isEffectiveBefore(lastCanonicalVersion));
Quite possibly this can be further optimized. But the principle, I hope, is clear.
Obviously, you won't be able to modify a local variable from lambda body. You need a wrapper of some kind that contains the thing you want to modify. An array is often used for that purpose
VERSION[] lastCanonicalVersion = {null}
....
if(...lastCanonicalVersion[0]...)
lastCanonicalVersion[0] = v;

Java: Get element before or after a given one in an Iterable

Is there a non verbose way (for example using a method call from an existing library, be it guava or similar) to retrieve the previous and the following element from an Iterable, given one of its elements?
I would like to have a general solution that fits for Iterable (or Collection if it is cool enough), so please do not post solutions that work just for Set or List and so on (maybe add a comment :) ).
I need either one or the other, I do not want to find both previous and following element in one method.
My solution is below. If you feel like commenting on returning null instead of throwing IllegalArgumentException or similar, please feel free to do so. The getElementBefore() method creates a new list, which I am not that happy with too.
public static <C> C getElementAfter(final C element, final Iterable<C> iterable) {
Iterator<C> iterator = iterable.iterator();
while (iterator.hasNext()) {
if (iterator.next().equals(element)) {
if (iterator.hasNext()) {
return iterator.next();
} else {
return null;
}
}
}
throw new IllegalArgumentException("Iterable does not contain element.");
}
public static <C> C getElementBefore(final C element, final Iterable<C> iterable) {
return getElementAfter(element, Lists.reverse(Lists.newArrayList(iterable)));
}
Returning null would probably make more sense in this case, as it may not be an exception.
Your getElementBefore implementation could be improved:
public static <C> C getElementBefore(final C element, final Iterable<C> iterable) {
C previous = null;
while (iterator.hasNext()) {
C current = iterator.next();
if (current.equals(element)) {
return previous;
} else {
previous = current;
}
}
return null;
}
I would do something like this:
Iterator<C> iterator = iterable.iterator();
C before = null;
C after = null;
while (iterator.hasNext()) {
C current = iterator.next();
if (current.equals(element)) {
if (iterator.hasNext()) {
after = iterator.next();
}
break;
}
before = current;
}
This should save the element before in before and the element after in after.

what is causing my NoSuchElementException for ArrayList

I know that there are lots of threads on NoSuchElementException in Java here but I still cannot figure out what is going on here
I am trying to come up with a solution for Transitive Dependencies Kata 18 which is posted at http://codekata.pragprog.com/2007/01/kata_eighteen_t.html
dependencies_for method is supposed to take in a char item and compute all dependencies for the item. The exception occurs when I try to add an element to finalDependencies ArrayList
This is the place where my NullPointerException occurs. I have traced all of these data structures and none of them have a Null value. I don't understand what is causing my exception here. Please see my code:
public class Test_Dependencies
{
public static void main(String[] args) {
Dependencies Dep = new Dependencies();
Dep.add_direct('A', "B C");
Dep.add_direct('B', "C D");
Dep.dependencies_for('A');
}
}
public class Dependencies {
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
public void add_direct(char mainItem, String dependentItems)
{
// code that works here
}
public String dependencies_for(char item)
{
ArrayList finalDependencies = new ArrayList<Character>();
Character key = new Character(item);
//get initial dependencies for the item and add them
ArrayList processingDependencies = dependenciesList.get(key);
Iterator itr = processingDependencies.iterator();
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// look again at each item in dependenciesList. If it is in the list then add it to processingDependencies
if(dependenciesList.containsKey(itr.next()) && !processingDependencies.contains(itr.next()))
{
processingDependencies.add(itr.next());
}
}
}
// turn finalDependencies into a string
itr = finalDependencies.iterator();
String allDependencies = "";
while(itr.hasNext())
{
allDependencies = allDependencies + " " + itr.next();
}
return allDependencies;
}
}
I am a bit perprlexed because processingDependencies and finalDependencies ArrayLists are not null. And processingDependencies arraylist contains an item
You are calling twice. The first call is "protected" by a matching hasNext Call. The second is not. Save the result of next into a temporary variable and use that, instead of using the value directly, since every call to next will try to advance the iterator first. In the good case, you get an exception. In the bad case, things seem to work, but your program is dealing with the wrong value.
You can't do this:
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// stuff removed
}
}
You must verify that iter.hasNext() is true prior to each call of itr.next(). What happens when you reach the last item in itr, but then call itr.next() three times?
Answer: NoSuchElementException. Check out Iterator
The problem is here:
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
You declare a hashmap called dependenciesList. You then try to instantiate that list, but what you actually do is create a local variable named the same thing. They are two separate variables. Then you try to use the one that hasn't been instantiated here:
ArrayList processingDependencies = dependenciesList.get(key);
What you need to do is instantiate the first dependenciesList instead of creating a new one
(I'm not a pro at java, but something like dependenciesList = new HashMap....() instead of HashMap<..> dependenciesList = new HashMap...() )

Is it possible to get the index of a for-each loop in Java

Given the code below, is it possible to remove the index of p from the properties list using this style of for loop in Java?
List<Properties> propertiesList = new ArrayList<Properties>();
String keyToDelete = "blah";
for(Properties p : propertiesList) {
if(p.getKey().equals(keyToDelete)) {
propertiesList.remove(index) //How to remove the element at index 'p'
}
}
This is how i would accomplish this with the other for loop
List<Properties> propertiesList = new ArrayList<Properties>();
String keyToDelete = "blah";
for(int i = 0; i < propertiesList.size(); i++) {
if(p.getKey().equals(keyToDelete)) {
propertiesList.remove(i);
}
}
The way to do this is with an explicit Iterator (no school like the old school!).
Iterator<Properties> it = propertiesList.iterator();
while (it.hasNext()) {
if (it.next().getKey().equals(keyToDelete)) {
it.remove();
}
}
Unlike the remove method on a list, the remove method on the iterator doesn't cause a concurrent modification. It's the only safe way to remove an element from a collection you're iterating over. As the javadoc for that method says:
The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.
No, you need to use the old-school for loop to get an index.
You could of course add it yourself to the for-each loop, but then you would most probably be better off using the old variant instead.
How about using proper Iterator and its remove method?
List<Properties> propertiesList = new ArrayList<Properties>();
String keyToDelete = "blah";
for (
Iterator<Properties> iter = propertiesList.iterator( );
iter.hasNext( );
)
{
Properties p = iter.next( );
if(p.getKey().equals(keyToDelete)) {
iter.remove( );
}
}
As Tim Anderson suggested you could also modify the list outside the loop
List<Properties> propertiesList = new ArrayList<Properties>();
String keyToDelete = "blah";
List<Properties> propertiesToRemove = new ArrayList<Properties>();
for(Properties p : propertiesList) {
if(p.getKey().equals(keyToDelete)) {
propertiesToRemove.add(p) ;
}
}
propertiesList.removeAll(propertiesToRemove);
As far as I know, foreach loop does not guarantee the order of elements it enumerates,
so if you will try Collection[i] you can get another element rather than currently iterated
It is can be clearly viewed in some multithreaded cases

Categories

Resources