Collections Arraygrenze überschreiten

skmCry

Mitglied
Hey,

hoffe ich bin hier im richtigen Forum gelandet.

Meine Frage bezieht sich auf Arrays:

Angenommen ich habe ein Array der Länge 4 und zähle durch dieses mittels einer for-Schleife durch.
Wenn ich dann aber innerhalb der Schleife immer auf das i+1 te Element (i = Zählvariable) zugreifen möchte, wird er mir verständlicherweise beim letzten Arrayfeld (i = 3) eine Exception werfen, da das Feld mit dem Index 4 nicht existiert.

Gibt es nun eine Möglichkeit zu sagen, dass er in diesem Fall wieder auf das vorderste Element zugreifen soll?
Bei obigem Beispiel also: Anstatt, dass er auf das Feld mit Index 4 zugreift, greift er auf das Feld mit dem Index 0 zu?
Im Prinzip soll also die Zahl 4 in 0 umgewandelt werden. Ist also wie bei einer Uhr, wo es ab Minute 59 wieder mit 00 weitergeht, in meinem Fall kommt aber nach der 3 die 0.

Wie lässt sich dies möglichst unkompliziert realisieren?

mfg skm

P.S: Hoffe, dass war verständlich genug ausgedrückt, wenn nicht einfach nachfragen.
 

skmCry

Mitglied
Oh gott, die Lösung ist aber simpel, an Modulo habe ich überhaupt nicht gedacht. Wollte mir schon lauter Hilfsmethoden schreiben, zum Umrechnen.

Naja vll sollte man ab und zu mal eine Pause machen^^

Jedenfalls tausend Dank für die rasche und hilfreiche Antwort eRaaaa :) Das klappt perfekt
 

Landei

Top Contributor
Hier eine andere, wiederverwendbare Lösungsmöglichkeit. Zuerst eine statische Methode:
Java:
    public static <T> Iterable<T> cycle(final Iterable<? extends T> iterable) {
        return new Iterable<T>() {
            public Iterator<T> iterator() {
                return new Iterator<T>() {
                    private Iterator<? extends T> it = iterable.iterator();
                    public boolean hasNext() {
                        if(it.hasNext()) {
                            return true;
                        } else {
                            it = iterable.iterator();
                            return it.hasNext();
                        }
                    }

                    public T next() {
                        if(hasNext()) {
                            return it.next();
                        } else {
                            throw new NoSuchElementException();
                        }
                    }

                    public void remove() {
                        throw new UnsupportedOperationException("Not supported yet.");
                    }
                };
            }
        };
    }

Damit kann man beliebige Collections und so endlos laufen lassen:
Java:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
for(int i : cycle(list)) {
     System.out.println(i);
}
 

skmCry

Mitglied
Echt ein tolles Forum, dass hier sofort so viele Vorschläge mit Codebeispielen kommen, vielen Dank und Kompliment =).

Werde vorläufig mit modulo arbeiten, aber das Codebeispiel im Hinterkopf behalten. Fehlerfangen bin ich immer etwas vorsichtig, was ich so bislang gelernt habe.

Was auch noch funktioniert, wäre das binäre &, z.B: array[(i - 1)&4]. Dann wird beispielsweise auch, wenn man bei der Zählvariable i mit 0 startet, auf das letzte Element des Arrays verwiesen, auch recht praktisch, da modulo keine negativen Werte umwandelt.
Allerdings weiß ich jetzt nicht genau, inwiefern das eine schöne Lösung ist.

Vielen Dank nochmal, Frage wurde mehr als zufriedenstellend beantwortet.
 

XHelp

Top Contributor
Binäre & ist hier ziemlich fehl am Platz. Wenn du das mathematische Modulo nachbauen willst, dann kannst du einfach
Code:
((i%4)+4)%4
rechnen.
 

XHelp

Top Contributor
Code:
irgendwas&4
ist entweder 4 oder 0 (und zwar in 4er Schritten), also wüsste ich jetzt nicht, wie es dir bei einem Index von 0..3 sinnvoll helfen sollte :bahnhof:
 
Zuletzt bearbeitet:

skmCry

Mitglied
Ja, dass hat mich eben auch gewundert, bin da zufällig draufgestoßen, als ich aus Versehen statt dem modulo Operator %, & eingegeben hatte.
Gib mal in Eclipse oder sonst wo, dass ein:

Java:
int[] testArray = {1, 2, 3, 4, 5, 6, 7, 8};
		
	for (int i = - 10; i < 10; i++) {
		System.out.println(testArray[(i-1)&7]);
	}

Wie man sehen kann, werden so, egal bei welcher Zählvariable, immer die passenden Felder (Wiederholung von 1 - 8) ausgegeben.
Woran liegt das?
 

DrPCox

Mitglied
Ja..der Modulo ist eine feine Sache...aber im Zweifelsfall hätte es ja auch eineinfaches if-konstrukt getan:

Java:
if (i == 4) {i = 0};
System.out.println(array[i]);
 

skmCry

Mitglied
Ja..der Modulo ist eine feine Sache...aber im Zweifelsfall hätte es ja auch eineinfaches if-konstrukt getan:

Java:
if (i == 4) {i = 0};
System.out.println(array[i]);

Schon klar, aber ich wollte ja gerade diesen Zugriff. Falls also -1 in der Zählvariable steht, soll er das letzte Element im Array auslesen und falls da +5 (bei einer Arraygröße von 4) steht, soll er das erste Element auslesen. Das selbe für -2 usw...
 
Zuletzt bearbeitet:

Antoras

Top Contributor
Ja, dass hat mich eben auch gewundert, bin da zufällig draufgestoßen, als ich aus Versehen statt dem modulo Operator %, & eingegeben hatte.
Gib mal in Eclipse oder sonst wo, dass ein:

Java:
int[] testArray = {1, 2, 3, 4, 5, 6, 7, 8};
		
	for (int i = - 10; i < 10; i++) {
		System.out.println(testArray[(i-1)&7]);
	}

Wie man sehen kann, werden so, egal bei welcher Zählvariable, immer die passenden Felder (Wiederholung von 1 - 8) ausgegeben.
Woran liegt das?
Zufall. Weißt du was
Code:
&
macht? Der Operator "verundet" die binären Darstellungen der Zahlen. Bsp:
Code:
7 = 0111

0 = 0000 --> 0000 & 0111 = 0000
1 = 0001 --> 0001 & 0111 = 0001
2 = 0010 --> 0010 & 0111 = 0010
3 = 0011 --> 0011 & 0111 = 0011
4 = 0100 --> 0100 & 0111 = 0100
...
7 = 0111 --> 0111 & 0111 = 0111
8 = 1000 --> 1000 & 0111 = 0000 // beginn von vorne
9 = 1001 --> 1001 & 0111 = 0001 // höherwertige Bits irrelevant
Da ein UND einzelne Bits auf null setzt, werden alle Zahlen größer 7 immer wieder auf einen Wert zwischen 0 und 7 gemappt, da alle höherwertigen Bits niemals miteinander verknüpft werden können. Wenn du immer eine 1 zum Binärwert dazu hängst kannst du dementsprechend auch größere Zahlenbereiche mappen, z.B. 15 (1111b), 31 (11111b) usw.

Bei einem Dezimalwert, dessen Binärdarstellung Nullen beinhaltet funktioniert das natürlich nicht mehr.
 
Zuletzt bearbeitet:

Andreas29

Bekanntes Mitglied
Hi,

da braucht man nicht "komisch" mit modulo rechnen, genauer gesagt braucht man überhaupt nicht rechnen. Eine simple und einfache if-Abfrage genügt:
Java:
package de.andreasgrund.cycle;

public class Cycle {

	private int [] intArray = {0,1,2,3,4,5,6,7,8,9};
	
	private static final int NUMBER_OF_CYCLES = 3;
	
	private void cycle(int [] intArray) {
		int currentCycle = 0;
		for(int i = 0; i < intArray.length; i++) {
			System.out.println(intArray[i]);
			if (i == intArray.length - 1) {
				i = -1; // -1 da die Zählvariable ja am ende eines jeden Schleifendurchlaufes hochgezählt wird
				currentCycle++;
			}
			if (currentCycle == NUMBER_OF_CYCLES) {
				return;
			}
		}
	}
	
	public static void main(String[] args) {
		Cycle c = new Cycle();
		c.cycle(c.intArray);
	}
}

Voll flexible, auf Collections leicht anpassbar (anstatt array.length einmal collection.size() aufgerufen fertig ist die Anpassung) und auf keine Größe beschränkt oder festgelegt. So einfach geht das... :)

Achso, die Konstante dient nur dazu, um die Endlosschleife kontrolliert zu beenden (womit es keine Endlosschleife mehr ist...)

Grüße und schönes Wochenende,
Andreas
 

skmCry

Mitglied
OK, alles klar, dann habe ich das mit dem binären & soweit verstanden und wie man jetzt bei dem "Arrayproblem" am Besten vorgeht. Wurden ja mehrere, teils sehr flexible Lösungsansätze geboten.

Vielen Dank und ebenfalls ein schönes Wochenende
skmCry
 
S

skmNew

Gast
ich geb auch mal meinen senf dazu. so geht es schneller:
Java:
for (int i = 1; i < a.length; i++) {
// tue was mit i
}

// tue was mit 0

mit (i + 1) % length geht es auch, aber warum umrechnen?
Java:
for (int i = 0; i <= a.length; i++) {
// tue was mit (i + 1) % a.length
}

mit (i + 1) & (length - 1) geht es, wenn sich length als 2^x formulieren lässt; dabei sind die unteren binärziffern 1.
Java:
for (int i = 0; i <= a.length; i++) {
// tue was mit (i + 1) & (a.length - 1)
}

z.b. dann
Java:
for (int i = 0; i < 100; i++) {
System.out.println(i & 15); /* denn 16 lässt sich als 2^4 formulieren */
}

alternativen innerhalb des schleifenrumpfes wären selbstverständlich eine weitere option, aber warum auch hier mehr aufwand betreiben wollen?
Java:
for (int i = 1; i < 100; i++) {
if (i < a.length) {
 // tue was mit i
} else {
 int tmp = i;
 while (tmp >= a.length) {
  tmp -= a.length;
 }
 // tue was mit tmp
}
}
 
S

skmNewNew

Gast
bei bsp. 2 u. 3 dann auch mit
Java:
for (int i = 0; i < a.length; i++) {
(i + 1) stellt ja schon die verschiebung dar.
 
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben