Valaki megértetné velem, hogy a foreach Javaban hogyan működik?
Itt egy példa.
String[] emberekTomb (vegyétek úgy, hogy fel van töltve)
For(String s : emberekTomb[] { kiadott parancs, ez lehet akármi }
Arra lennék kíváncsi, hogy tulajdonképpen a háttérben ennél mi történik? Annyit látok, hogy a kettőt valahogy osszehasonlitja, végig egy rajta, de nem értem mi alapján, hisz a String s-t csak ott hoztam létre,és nem tartalmaz semmit ami alapján össze lehetne hasonlítani vele a tömböt..
Nincs semmiféle összehasonlítás, eleve mit hasonlítanál egy string-en meg egy string tömbön?
A foreach végigiterál egy valamilyen gyűjteményen. Jelen esetben egyesével belerakja az emberekTomb elemeit a s változóba.
string[] t;
for(int i = 0; i < t.length; i++)
{
string s = t[i];
...
}
A ... a kódod helye, az a fölötti rész a foreach. Azt jelenti.
Túlgondolod.
A foreach, a for, és minden egyéb ehhez hasonló dolog egy előre megírt program amit használsz. Akár mennyire bonyolultnak tűnik is. Úgy próbáld megérteni, hogy rájössz miért van rá szükséged.
Mit csinál a foreach? Végigiterál (végiglépked) egy adott tömb vagy lista elemein, az elejétől egészen a legvégéig.
Mit csinál a for? Igazából ugyan azt, amit a foreach, csak bele van építve egy iterációs változó, de ezt te kézzel is beteheted a foreacbe ha nagyon akarod. De minek tennéd, hisz azért van a kettő szétválasztva, hogy azt használd amelyik neked éppen kell.
A lényeg:
Foreach (javabna nem írjuk ki, hogy foreach, csak a felépítésből jöhetsz rá)
int[] szamok_tomb = new int[] {1,2,3,4,5}; //deklarálsz, és definiálsz egy tömböt amiben van 5 db szám
for (int tomb_eleme : szamok_tomb) //végigiterálsz a tömb összes elemén egyesével, úgy, hogy megmondod a foreachnek, hogy a tomb_eleme legyen az a változó, ami az aktuális elem (ahol jár)
{
System.out.println(tomb_eleme); // mindent ami ide írsz, annyiszor fog lefutni, ahány elem még van a tömbben.
}
Tehát az első körben a tömb 0. indexelemét vizsgálod, így a legelső kiírásod az lesz, hogy 1, mivel ez a tömb 0. eleme. Ugyan ez az objektumoknál:
Van egy classod aminek a neve: Ember
- nev
- kor
tehát ebből bármikor tudsz példányosítani egy embert:
Ember józsi = new Ember();
van egy józsi nevű Ember típusú páldányod. Ennek tükrében:
for (Ember aktualis_ember : Emberek) // az Embereket itt vedd egy olyan listának ami Ember típusú objektumokkal van feltöltve.
// Pl: józsi, béla, laci, stb. Más adataik (fieldjeik) vannak, de ugyan az a típus: Ember
{
System.out.println(aktualis_ember.getNev()); //a .getNev egy getter a névre. Ezzel ne foglalkozz. A visszatérési értéke az Ember class nev értéke.
}
Itt ugyan az történik, csakk egy objektumokból álló listán vagy tömbön mész végig, és a lista típusa, tehát maga az objektum típúsú lesz egy elem, azaz Ember.
Baromi bonyolultnak tűnhet, de ha ezt egyszer megérted, azon fogsz röhögni, hogy ez a világ legyegyszerűbb dolga.
Hajrá!
# 7 vagyok
aki lepontozott igazán leírhatná, hogy miben nem ért velem egyet, mert én is szeretek ám tanulni az okosabbtól. Köszönöm
A foreach ciklushoz kell valami, ami felsorolható - egy tömb, egy lista, stb. Általában ezek kétfélék lehetnek:
- Vagy ismert méretű adatszerkezetről van szó, vagyis meg tudják mondani, hogy jelenleg hány elemük van, és egy általam megadott indexű elemet vissza is tudnak adni
- Vagy ismeretlen méretű adatszerkezetről van szó, de ebben az esetben is meg tudják mondani, hogy van-e következő elem, és ha igen, meg is tudják adni azt.
Erre ugyanis szükségünk van, hogy be tudjuk őket járni. Csak a probléma ott van, hogy ezek eltérő módon lehetnek implementálva:
class Array<T> {
.. public int GetCount();
.. public T Get(int index);
}
class List<T> {
.. public int GetLength();
.. public T ElementAt(int index);
}
class Sequence<T> {
.. public bool HasNext();
.. public T GetNext();
}
(Bocsi, én C# fejlesztő vagyok, nem Java, de a lényeg átjön szerintem.)
Ezeket valahogy közös nevezőre kell hozni, vagyis el kell érni azt, hogy egységes metódusokkal tudjuk kezelni őket. Ezért találták ki az iterator design pattern-t, amiről itt olvashatsz:
Ez a tervezési minta két interfészt ír elő:
- a Container interfészt, egy szál művelettel ami visszaad egy Iterator-t,
- az Iterator interfészt, aminek két művelete van:
.. 1) meg tudja mondani, hogy van-e következő eleme a Container-nek,
.. 2) megadja a következő elemet, és léptet
Java-ban a Container interfész megfelelője az Iterable, míg az Iterator - nagyon szellemes módon - Iterator névre hallgat.
Vagyis a kódunk valahogy így módosul:
interface Container<T> {
.. Iterator<T> GetIterator();
}
interface Iterator<T> {
.. bool HasNext();
.. T GetNext();
}
class Array<T> : Container<T> { //képzeljük el, hogy van konstruktora is
.. public int GetCount();
.. public T Get(int index);
.. public Iterator<T> GetIterator() {
.. .. return new ArrayIterator<T>(this);
.. }
}
class ArrayIterator<T> : Iterator<T> {
.. private readonly Array<T> array;
.. private int index = 0;
.. public ArrayIterator(Array<T> array) { this.array = array; }
.. public bool HasNext() { return index < array.GetCount() - 1; }
.. public T GetNext() {
.. .. if (index == array.GetLength()) throw new Exception();
.. .. return array.Get(index++);
.. }
}
És ezt az egész hóbelebancot így lehet használni:
void ForEach<T>(Container<T> container, Action<int> codeToRun) {
.. Iterator<T> iterator = container.GetIterator();
.. while (iterator.HasNext()) {
.. .. codeToRun(iterator.GetNext());
.. }
}
Array<int> array = new Array<int>(5, 4, 3, 2, 1);
ForEach(array, x => Console.WriteLine(x));
És a foreach ciklus a fenti metódus kódját teszi nyelvi elemmé, így lesz nekünk olyanunk, hogy
for (int x : array) {
.. //codeToRun
}
A háttérben ez erre a logikára fordul le:
Iterator<T> iterator = array.GetIterator();
while (iterator.HasNext()) {
.. T x = iterator.GetNext();
.. //codeToRun
}
Tehát, ha van egy saját osztályod, amit foreach-elhetővé akarsz tenni, akkor:
1) az osztályodnak implementálnia kell az Iterable interfészt úgy, hogy a második pontban említett osztály példányát adja vissza
2) írsz egy külön osztályt, ami implementálja az Iterator interfészt
És már készen is vagy.
A háttérben ez erre a logikára fordul le:
Iterator<T> iterator = array.GetIterator();
while (iterator.HasNext()) {
.. T x = iterator.GetNext();
.. //codeToRun
}
Akarom mondani:
Iterator<int> iterator = array.GetIterator();
while (iterator.HasNext()) {
.. int x = iterator.GetNext();
.. //codeToRun
}
Kapcsolódó kérdések:
Minden jog fenntartva © 2025, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!