I have an Iterator - placed somewhere in the middle of my collection.
I want to loop over the collection from there on, returning a special element if I find it.
If I reach !hasNext() then I want to start at the begining, but I want to stop if I reach the place where I started first.
The best Idea how to solve that seems currently to save the "first" (wherever the iterator pointed when I started) element and then stop if I find that one again.
And that works as long as items can occure only once in my collection (i.e. in a HasSet).
Any better ideas how to do such thing? Iterator doesn't seem to supply a pointer/number back to me that I could compare.
With Guava Iterators (Java 7):
Iterator<YourType> iterator = Iterators.concat(yourIteratorPlaceSomewhereInMiddle, Iterators.limit(yourCollection.iterator(), positionOfSomewhereInMiddle));
With Streams (Java 8):
Optional<YourType> theAnswer = IntStream.iterate(positionOfSomewhereInMiddle, pos -> ++pos)
.map(pos -> pos % sizeOfCollection)
.mapToObj(yourCollection::get)
.limit(sizeOfCollection)
.filter(element -> element is 42)
.findFirst();
If the collection is a list, then it can be done with below code
private void Object traverseList(List namesList, int startIndex ) {
int index = 0;
Iterator iterator = namesList.listIterator(startIndex);
while (iterator.hasNext() && index < namesList.size()){
Object element = iterator.next();
/*if(element.isSpecialElement()){
return element;
}
*/
index++;
System.out.println(element);
if(!iterator.hasNext()){
iterator = namesList.iterator();
}
}
}
Since you want to transverse all the elements in the list, I am making use of list size. And during iteration, if the special element is found, it can be returned.
To start to iterate a Set from a definedValue I do :
public void iterate(Set<Sample> set, Sample definedValue){
Iterator<Sample> iterator = set.iterator();
while(iterator.hasNext()){
Sample currentSample = iterator.next();
if(currentSample.equals(definedValue)){
while(iterator.hasNext()){
Sample sampleToConsider = iterator.next();
//Then do anything
}
}
}
}
The solution becomes more simple if you:
Don't use Iterator, it makes it more complicated
Use a List instead of Set as Set is ill-suited for this use case
public static void main(String[] args) {
Set<String> yourStartingCollection = new HashSet<>();
List<String> fooList = new ArrayList<>(yourStartingCollection);
Optional<String> specialElement = findSpecialElementStartingFromMiddle(fooList);
if (specialElement.isPresent()) {
// found it!
}
}
private static Optional<String> findSpecialElementStartingFromMiddle(List<String> elements) {
int middleIndex = elements.size() / 2;
Optional<String> result = Optional.empty();
for (int i = middleIndex; i < elements.size(); i++) {
String element = elements.get(i);
if (isSpecial(element)) {
result = Optional.of(element);
break;
}
}
if (result.isPresent()) {
return result;
}
for (int i = 0; i < middleIndex; i++) {
String element = elements.get(i);
if (isSpecial(element)) {
result = Optional.of(element);
break;
}
}
return result;
}
private static boolean isSpecial(String element) {
return element.equals("I'm special");
}
Related
I have a set of sets of integers: Set<Set<Integer>>.
I need to add integers to the set of sets as if it were a double array. So add(2,3) would have to add integer 3 to the 2nd set.
I know a set is not very suitable for this operation but it's not my call.
The commented line below clearly does not work but it shows the intention.
My question is how to add an integer to a set while iterating?
If it's necessary to identify each set, how would one do this?
#Override
public void add(int a, int b) {
if (!isValidPair(a, b)) {
throw new IllegalStateException("!isValidPair does not hold for (a,b)");
}
Iterator<Set<Integer>> it = relation.iterator();
int i = 0;
while (it.hasNext() && i <= a) {
//it.next().add(b);
i++;
}
}
One fundamental things you should be aware of, for which makes all existing answer in this question not working:
Once an object is added in a Set (similarly, as key in Map), it is not supposed to change (at least not in aspects that will change its equals() and hashCode()). The "Uniqueness" checking is done only when you add the object into the Set.
For example
Set<Set<Integer>> bigSet = new HashSet<>();
Set<Integer> v1 = new HashSet<>(Arrays.asList(1,2));
bigSet.add(v1);
System.out.println("contains " + bigSet.contains(new HashSet<>(Arrays.asList(1,2)))); // True
v1.add(3);
System.out.println("contains " + bigSet.contains(new HashSet<>(Arrays.asList(1,2)))); // False!!
System.out.println("contains " + bigSet.contains(new HashSet<>(Arrays.asList(1,2,3)))); // False!!
You can see how the set is corrupted. It contains a [1,2,3] but contains() does not work, neither for [1,2] nor [1,2,3].
Another fundamental thing is, your so-called '2nd set' may not make sense. Set implementation like HashSet maintain the values in arbitrary order.
So, with these in mind, what you may do is:
First find the n-th value, and remove it
add the value into the removed value set
re-add the value set.
Something like this (pseudo code again):
int i = 0;
Set<Integer> setToAdd = null;
for (Iterator itr = bigSet.iterator; itr.hasNext(); ++i) {
Set<Integer> s = itr.next();
if (i == inputIndex) {
// remove the set first
itr.remove();
setToAdd = s;
break;
}
}
// update the set and re-add it back
if (setToAdd != null) {
setToAdd.add(inputNumber);
bigSet.add(setToAdd);
}
Use a for-each loop and make your life easier.
public boolean add(int index, int value) {
// because a and b suck as variable names
if (index < 0 || index >= values.size()) {
return false;
}
int iter = 0;
for (Set<Integer> values : relation) {
if (iter++ == index) {
return values.add(value):
}
}
return false;
}
Now all you have to figure out is what to do if relation is unordered, as a Set or a relation are, because in that case a different Set<Integer> could match the same index each time the loop executes.
Use can use Iterators of Guava library like this :
#Override
public void add(int a, int b) {
if (!isValidPair(a, b)) {
throw new IllegalStateException("!isValidPair does not hold for (a,b)");
}
Iterators.get(relation.iterator(), a).add(b);
}
Edit : without Guava:
Iterator<Set<Integer>> iterator = relation.iterator();
for(int i = 0; i < a && iterator.hasNext(); ++i) {
iterator.next();
}
if(iterator.hasNext()) {
iterator.next().add(b);
}
I have the following map: Map<Integer,String[]> map = new HashMap<Integer,String[]>();
The keys are integers and the values are arrays (could also be replaced by lists).
Now, I would like to get all possible combinations of the values among the keys. For example, let's say the map contains the following entries:
key 1: "test1", "stackoverflow"
key 2: "test2", "wow"
key 3: "new"
The combinations consists of
("test1","test2","new")
("test1","wow","new")
("stackoverflow", "test2", "new")
("stackoverflow", "wow", "new")
For this I imagine a method boolean hasNext() which returns true if there is a next pair and a second method which just returns the next set of values (if any).
How can this be done? The map could also be replaced by an other data structure.
The algorithm is essentially almost the same as the increment algorithm for decimal numbers ("x -> x+1").
Here the iterator class:
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TreeSet;
public class CombinationsIterator implements Iterator<String[]> {
// Immutable fields
private final int combinationLength;
private final String[][] values;
private final int[] maxIndexes;
// Mutable fields
private final int[] currentIndexes;
private boolean hasNext;
public CombinationsIterator(final Map<Integer,String[]> map) {
combinationLength = map.size();
values = new String[combinationLength][];
maxIndexes = new int[combinationLength];
currentIndexes = new int[combinationLength];
if (combinationLength == 0) {
hasNext = false;
return;
}
hasNext = true;
// Reorganize the map to array.
// Map is not actually needed and would unnecessarily complicate the algorithm.
int valuesIndex = 0;
for (final int key : new TreeSet<>(map.keySet())) {
values[valuesIndex++] = map.get(key);
}
// Fill in the arrays of max indexes and current indexes.
for (int i = 0; i < combinationLength; ++i) {
if (values[i].length == 0) {
// Set hasNext to false if at least one of the value-arrays is empty.
// Stop the loop as the behavior of the iterator is already defined in this case:
// the iterator will just return no combinations.
hasNext = false;
return;
}
maxIndexes[i] = values[i].length - 1;
currentIndexes[i] = 0;
}
}
#Override
public boolean hasNext() {
return hasNext;
}
#Override
public String[] next() {
if (!hasNext) {
throw new NoSuchElementException("No more combinations are available");
}
final String[] combination = getCombinationByCurrentIndexes();
nextIndexesCombination();
return combination;
}
private String[] getCombinationByCurrentIndexes() {
final String[] combination = new String[combinationLength];
for (int i = 0; i < combinationLength; ++i) {
combination[i] = values[i][currentIndexes[i]];
}
return combination;
}
private void nextIndexesCombination() {
// A slightly modified "increment number by one" algorithm.
// This loop seems more natural, but it would return combinations in a different order than in your example:
// for (int i = 0; i < combinationLength; ++i) {
// This loop returns combinations in the order which matches your example:
for (int i = combinationLength - 1; i >= 0; --i) {
if (currentIndexes[i] < maxIndexes[i]) {
// Increment the current index
++currentIndexes[i];
return;
} else {
// Current index at max:
// reset it to zero and "carry" to the next index
currentIndexes[i] = 0;
}
}
// If we are here, then all current indexes are at max, and there are no more combinations
hasNext = false;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Remove operation is not supported");
}
}
Here the sample usage:
final Map<Integer,String[]> map = new HashMap<Integer,String[]>();
map.put(1, new String[]{"test1", "stackoverflow"});
map.put(2, new String[]{"test2", "wow"});
map.put(3, new String[]{"new"});
final CombinationsIterator iterator = new CombinationsIterator(map);
while (iterator.hasNext()) {
System.out.println(
org.apache.commons.lang3.ArrayUtils.toString(iterator.next())
);
}
It prints exactly what's specified in your example.
P.S. The map is actually not needed; it could be replaced by a simple array of arrays (or list of lists). The constructor would then get a bit simpler:
public CombinationsIterator(final String[][] array) {
combinationLength = array.length;
values = array;
// ...
// Reorganize the map to array - THIS CAN BE REMOVED.
I took this as a challenge to see whether the new Java 8 APIs help with these kind of problems. So here's my solution for the problem:
public class CombinatorIterator implements Iterator<Collection<String>> {
private final String[][] arrays;
private final int[] indices;
private final int total;
private int counter;
public CombinatorIterator(Collection<String[]> input) {
arrays = input.toArray(new String[input.size()][]);
indices = new int[arrays.length];
total = Arrays.stream(arrays).mapToInt(arr -> arr.length)
.reduce((x, y) -> x * y).orElse(0);
counter = 0;
}
#Override
public boolean hasNext() {
return counter < total;
}
#Override
public Collection<String> next() {
List<String> nextValue = IntStream.range(0, arrays.length)
.mapToObj(i -> arrays[i][indices[i]]).collect(Collectors.toList());
//rolling carry over the indices
for (int j = 0;
j < arrays.length && ++indices[j] == arrays[j].length; j++) {
indices[j] = 0;
}
counter++;
return nextValue;
}
}
Note that I don't use a map as an input as the map keys actually don't play any role here. You can use map.values() though to pass in the input for the iterator. With the following test code:
List<String[]> input = Arrays.asList(
new String[] {"such", "nice", "question"},
new String[] {"much", "iterator"},
new String[] {"very", "wow"}
);
Iterator<Collection<String>> it = new CombinatorIterator(input);
it.forEachRemaining(System.out::println);
the output will be:
[such, much, very]
[nice, much, very]
[question, much, very]
[such, iterator, very]
[nice, iterator, very]
[question, iterator, very]
[such, much, wow]
[nice, much, wow]
[question, much, wow]
[such, iterator, wow]
[nice, iterator, wow]
[question, iterator, wow]
When I acces to list of list with this function,It make ConcurrentModificationException in second for loop but i don't understand why this Exception is triggered .
public static List<List<Dico>> weight_term(List<List<Dico>> sublists ,List<String> sinificativ )
{
List<List<Dico>> matrix_node_term = new ArrayList<>();
List<Dico> list_node = new ArrayList<>();// a new list for node
for (List<Dico> sublist : sublists) // to get each sublist List<Dico>
{
for (Dico dico : sublist) // get each Dico in the sublist -->ConcurrentModificationException
{
String term =dico.getTerm();
int id = dico.getDocId();
if(sinificativ.contains(term)) // if this term exist in sinificativ erm list
{
list_node.add(dico); // it add to list_node
}
else
{
list_node.add(new Dico(id,term,0.0)); // it add to list_node with null weigth
}
}
matrix_node_term.add(list_node); // add each list to list of list
}
return matrix_node_term;
}
The dico class is used to store term,id of document and the weight of this term in that document :
public class Dico implements Comparable
{
private final String m_term;
private double m_weight;
private final int m_Id_doc;
public Dico(int Id_Doc,String Term,double tf_ief )
{
this.m_Id_doc = Id_Doc;
this.m_term = Term;
this.m_weight = tf_ief;
}
}
This Exception is triggered without any modification in the sutucte of list or its elements .
Probleme comes from a function used to split List in multiple List:
List<List<Dico>> sublists = new ArrayList<>(change);
for (int i = 0; i < change; i++)
{
sublists.add(list.subList(changes[i],changes[i + 1]));
}
A solution comes from pbabcdefp
List<List<Dico>> sublists = new ArrayList<>(change);
for (int i = 0; i < change; i++)
{
sublists.add(newArrayList<Dico>(list.subList(changes[i], changes[i + 1])));
}
thank you for your help
I'm learning Android and Java i have created a class let's say like this
class x(){
public int a;
public string b;
}
and then i initiate a list of this class and then added values to its properties like this
public ArrayList<x> GetList(){
List<x> myList = new ArrayList<x>();
x myObject = new x();
myObject.a = 1;
myObject.b = "val1";
mylist.add(x);
y myObject = new y();
myObject.a = 2;
myObject.b = "val2";
mylist.add(y);
return myList;
}
My Question is how can i loop through what GetList() return
i have tried
ArrayList<x> list = GetList();
Iterator<x> iterator = list.iterator();
but i don't know if this is the right way of doing this, plus i don't know what to do next i have added a breakpoint on the Iterator but it seemed to be null , the list have values thought
There are two ways to do this:
A for loop
Using the iterator method.
for loop:
for(x currentX : GetList()) {
// Do something with the value
}
This is what's called a "for-each" loop, and it's probably the most common/preferred method of doing this. The syntax is:
for(ObjectType variableName : InCollection)
You could also use a standard for loop:
ArrayList<x> list = GetList();
for(int i=0; i<list.size(); i++) {
x currentX = list.get(i);
// Do something with the value
}
The syntax for this is:
for(someStartingValue; doSomethingWithStartingValue; conditionToStopLooping)
iterator method:
Iterator<x> iterator = GetList().iterator();
while(iterator.hasNext()) {
x currentX = iterator.next();
// Do something with the value
}
You can loop through your array with a for-each loop:
for (x item: GetList()) {
doSomethingWithEachValue(item);
}
I guess you can iterate through the arraylist a number of ways. One way is the iterator:-
ArrayList<String> al = new ArrayList<String>();
al.add("C");
al.add("A");
al.add("E");
al.add("B");
al.add("D");
al.add("F");
System.out.print("Original contents of al: ");
Iterator<String> itr = al.iterator();
while (itr.hasNext()) {
String element = itr.next();
System.out.print(element + " ");
}
Another way would be a loop:
for(int i = 0; i < list.size(); i++){
list[i].a = 29;
}
Hope this helps in any way.
Ref
http://www.tutorialspoint.com/java/java_using_iterator.htm
http://examples.javacodegeeks.com/core-java/util/arraylist/arraylist-in-java-example-how-to-use-arraylist/
UPDATE
I thought that I should just put this out there from research due to the comment below about performance.
The Android docs
http://developer.android.com/training/articles/perf-tips.html
states:
The enhanced for loop (also sometimes known as "for-each" loop) can be used for collections >that implement the Iterable interface and for arrays. With collections, an iterator is >allocated to make interface calls to hasNext() and next(). With an ArrayList, a hand-written >counted loop is about 3x faster (with or without JIT), but for other collections the enhanced >for loop syntax will be exactly equivalent to explicit iterator usage.
There are several alternatives for iterating through an array:
static class Foo {
int mSplat;
}
Foo[] mArray = ...
public void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
}
public void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
public void two() {
int sum = 0;
for (Foo a : mArray) {
sum += a.mSplat;
}
}
zero() is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the
loop.
one() is faster. It pulls everything out into local variables,
avoiding the lookups. Only the array length offers a performance
benefit.
two() is fastest for devices without a JIT, and indistinguishable
from one() for devices with a JIT. It uses the enhanced for loop
syntax introduced in version 1.5 of the Java programming language.
So, you should use the enhanced for loop by default, but consider a hand-written counted loop for performance-critical ArrayList iteration. Also this is stated by Josh Bloch's Effective Java, item 46. The iterator and the index variables are both just clutter. Furthermore, they represent opportunities for error.
The preferred idiom for iterating over collections and arrays
for(Element e : elements){
doSomething(e);
}
Josh also states when you see the colon : read it as "In". The loop reads as for each element e in elements. I do not claim this work as my own even though I wish it was. If you want to learn more about efficient code then I suggest reading Josh Bloch's Effective Java.
Try the following:
class x {
public int a;
public String b;
}
private void test() {
List<x> items = getList();
for (x item: items) {
System.out.print("val: " + item.a);
}
}
private List<x> getList() {
List<x> items = new ArrayList<x>();
x oneObject = new x();
oneObject.a = 1;
oneObject.b = "val1";
items.add(oneObject);
x anotherObject = new x();
anotherObject.a = 2;
anotherObject.b = "val2";
items.add(anotherObject);
return items;
}
I have seen a number of questions dealing with finding the min index. There is a solution on this related question, that uses 2 built-in functions, min and then indexOf. The problem with that approach is that it goes over the whole list twice. Is there any single built-in function for minimum/maximum indices?
As of Java 7, there is no such method; you would have to implement it yourself. Keep in mind that for a List, there's not necessarily one correct answer to this question, as a single object can be added to a List multiple times, or you could have multiple equal objects.
Here's a general solution to that problem along with a short example.
It iterates the list exactly once and returns the index of the minimal item and the minimal item itself. It is implemented to return the first index and item, if the smallest item has one or more equal items in the list.
You can adjust the immutable ListMin<T> class to your needs and adapt the code to find the maxima.
public class ListMin<T> {
final int index;
final T item;
public ListMin(int index, T item) {
this.index = index;
this.item = item;
}
public static <E extends Comparable<E>> ListMin<E> getListMin(List<E> list) {
if (list.size() == 0) {
// throw exception, do what you want.
}
ListIterator<E> it = list.listIterator();
int minIndex = 0;
E minItem = it.next(); // first is minimum
while (it.hasNext()) {
E item = it.next();
if (item.compareTo(minItem) < 0) {
minItem = item;
minIndex = it.previousIndex();
}
}
return new ListMin<E>(minIndex, minItem);
}
public static void main(String[] args) {
List<String> list = Arrays.asList("B", "A", "C");
ListMin<String> listMin = getListMin(list);
System.out.println(listMin.index);
System.out.println(listMin.item);
}
}