JavaRush /جاوا بلاگ /Random-UR /کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کیسے دہ...
Viacheslav
سطح

کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کیسے دہرایا، دہرایا گیا، لیکن اعادہ نہیں کیا گیا

گروپ میں شائع ہوا۔

تعارف

لوپس پروگرامنگ زبانوں کے بنیادی ڈھانچے میں سے ایک ہیں۔ مثال کے طور پر، اوریکل کی ویب سائٹ پر ایک سیکشن ہے " سبق: زبان کی بنیادی باتیں "، جس میں لوپس کا ایک الگ سبق ہے " بیان کے لیے "۔ آئیے بنیادی باتوں کو تازہ کریں: لوپ تین اظہارات (بیانات) پر مشتمل ہے: ابتداء (ابتدائی)، شرط (ختم) اور اضافہ (اضافہ):
کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کس طرح دہرایا، اعادہ کیا، لیکن اعادہ نہیں کیا - 1
دلچسپ بات یہ ہے کہ وہ سب اختیاری ہیں، یعنی اگر ہم چاہیں تو لکھ سکتے ہیں:
for (;;){
}
سچ ہے، اس صورت میں ہمیں ایک لامتناہی لوپ ملے گا، کیونکہ ہم لوپ سے باہر نکلنے (ختم ہونے) کی شرط نہیں بتاتے ہیں۔ ابتدائی اظہار صرف ایک بار انجام دیا جاتا ہے، اس سے پہلے کہ پورے لوپ کو انجام دیا جائے۔ یہ ہمیشہ یاد رکھنے کے قابل ہے کہ ایک سائیکل کا اپنا دائرہ کار ہوتا ہے۔ اس کا مطلب ہے کہ ابتداء ، ختم ، اضافہ اور لوپ باڈی ایک ہی متغیر کو دیکھتے ہیں۔ گھوبگھرالی منحنی خطوط وحدانی کا استعمال کرتے ہوئے دائرہ کار کا تعین کرنا ہمیشہ آسان ہوتا ہے۔ بریکٹ کے اندر موجود ہر چیز بریکٹ کے باہر نظر نہیں آتی، لیکن بریکٹ کے باہر کی ہر چیز بریکٹ کے اندر نظر آتی ہے۔ ابتداء محض ایک اظہار ہے۔ مثال کے طور پر، متغیر کو شروع کرنے کے بجائے، آپ عام طور پر ایسے طریقہ کو کال کرسکتے ہیں جو کچھ بھی واپس نہیں کرے گا۔ یا پہلے سیمیکولن سے پہلے خالی جگہ چھوڑ کر اسے چھوڑ دیں۔ مندرجہ ذیل اظہار برطرفی کی شرط کی وضاحت کرتا ہے ۔ جب تک یہ سچ ہے ، لوپ کو عمل میں لایا جاتا ہے۔ اور اگر غلط ہے تو، ایک نئی تکرار شروع نہیں ہوگی۔ اگر آپ نیچے دی گئی تصویر کو دیکھتے ہیں، تو ہمیں تالیف کے دوران ایک غلطی ملتی ہے اور IDE شکایت کرے گا: لوپ میں ہمارا اظہار ناقابل رسائی ہے۔ چونکہ ہمارے پاس لوپ میں ایک بھی تکرار نہیں ہوگی، اس لیے ہم فوراً باہر نکل جائیں گے، کیونکہ غلط:
کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کیسے دہرایا، دہرایا، لیکن اعادہ نہیں کیا - 2
برطرفی کے بیان میں اظہار پر نظر رکھنے کے قابل ہے : یہ براہ راست تعین کرتا ہے کہ آیا آپ کی درخواست میں لامتناہی لوپ ہوں گے۔ اضافہ آسان ترین اظہار ہے۔ یہ لوپ کے ہر کامیاب تکرار کے بعد عمل میں لایا جاتا ہے۔ اور اس اظہار کو بھی چھوڑا جا سکتا ہے۔ مثال کے طور پر:
int outerVar = 0;
for (;outerVar < 10;) {
	outerVar += 2;
	System.out.println("Value = " + outerVar);
}
جیسا کہ آپ مثال سے دیکھ سکتے ہیں، لوپ کی ہر تکرار کو ہم 2 کے انکریمنٹ میں بڑھائیں گے، لیکن صرف اس وقت تک جب تک کہ قدر 10outerVar سے کم ہو ۔ کچھ بھی شامل ہو سکتا ہے. لہذا، کوئی بھی انکریمنٹ کے بجائے کمی کے استعمال سے منع نہیں کرتا، یعنی قدر کو کم کریں. آپ کو ہمیشہ انکریمنٹ کی تحریر کی نگرانی کرنی چاہیے۔ پہلے اضافہ اور پھر اسائنمنٹ کرتا ہے، لیکن اگر اوپر کی مثال میں ہم اس کے برعکس لکھتے ہیں، تو ہمیں ایک لامحدود لوپ ملے گا، کیونکہ متغیر کو کبھی بھی تبدیل شدہ قدر نہیں ملے گی: اس صورت میں اس کا حساب اسائنمنٹ کے بعد کیا جائے گا۔ ویسے، یہ ویو انکریمنٹ کے ساتھ بھی ایسا ہی ہے ۔ مثال کے طور پر، ہمارے پاس ایک لوپ تھا: +=outerVar=+++
String[] names = {"John","Sara","Jack"};
for (int i = 0; i < names.length; ++i) {
	System.out.println(names[i]);
}
سائیکل نے کام کیا اور کوئی مسئلہ نہیں تھا۔ لیکن پھر ریفیکٹرنگ آدمی آیا. وہ اضافہ سمجھ نہیں پایا اور صرف یہ کیا:
String[] names = {"John","Sara","Jack"};
for (int i = 0; i < names.length;) {
	System.out.println(names[++i]);
}
اگر قیمت کے سامنے اضافہ کا نشان ظاہر ہوتا ہے، تو اس کا مطلب ہے کہ یہ پہلے بڑھے گا اور پھر اس جگہ پر واپس آجائے گا جہاں اس کی نشاندہی کی گئی ہے۔ اس مثال میں، ہم فوری طور پر پہلے والے کو چھوڑ کر انڈیکس 1 پر عنصر کو صف سے نکالنا شروع کر دیں گے۔ اور پھر انڈیکس 3 پر ہم " java.lang.ArrayIndexOutOfBoundsException " کی غلطی کے ساتھ کریش ہو جائیں گے ۔ جیسا کہ آپ نے اندازہ لگایا ہوگا، اس سے پہلے صرف اس وجہ سے کام ہوا کہ تکرار مکمل ہونے کے بعد اضافہ کہا جاتا ہے۔ اس اظہار کو تکرار میں منتقل کرتے وقت، سب کچھ ٹوٹ گیا۔ جیسا کہ یہ پتہ چلتا ہے، یہاں تک کہ ایک سادہ لوپ میں بھی آپ گڑبڑ کر سکتے ہیں) اگر آپ کے پاس ایک صف ہے، تو شاید تمام عناصر کو ظاہر کرنے کا کوئی آسان طریقہ ہے؟
کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کیسے دہرایا، دہرایا، لیکن اعادہ نہیں کیا - 3

ہر ایک لوپ کے لیے

Java 1.5 کے ساتھ شروع کرتے ہوئے، جاوا کے ڈویلپرز نے ہمیں for each loopگائیڈ میں اوریکل سائٹ پر بیان کردہ ایک ڈیزائن دیا جسے " The For-Each Loop " یا ورژن 1.5.0 کے لیے کہا جاتا ہے ۔ عام طور پر، یہ اس طرح نظر آئے گا:
کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کیسے دہرایا، دہرایا، لیکن اعادہ نہیں کیا - 4
آپ جاوا لینگویج اسپیسیفیکیشن (JLS) میں اس تعمیر کی تفصیل پڑھ سکتے ہیں تاکہ یہ یقینی بنایا جا سکے کہ یہ جادو نہیں ہے۔ اس تعمیر کو باب میں بیان کیا گیا ہے " 14.14.2. بیان کے لیے بڑھایا گیا ہے "۔ جیسا کہ آپ دیکھ سکتے ہیں، ہر ایک لوپ کے لیے arrays اور ان کے ساتھ استعمال کیا جا سکتا ہے جو java.lang.Iterable انٹرفیس کو لاگو کرتے ہیں ۔ یعنی، اگر آپ واقعی چاہتے ہیں، تو آپ java.lang.Iterable انٹرفیس کو نافذ کر سکتے ہیں اور ہر ایک لوپ کے لیے آپ کی کلاس کے ساتھ استعمال کیا جا سکتا ہے۔ آپ فوراً کہیں گے، "ٹھیک ہے، یہ ایک قابل تکرار شے ہے، لیکن ایک صف کوئی چیز نہیں ہے۔" اور آپ غلط ہوں گے، کیونکہ... جاوا میں، arrays متحرک طور پر تخلیق کردہ اشیاء ہیں. زبان کی تفصیلات ہمیں یہ بتاتی ہیں: " جاوا پروگرامنگ زبان میں، صفیں آبجیکٹ ہیں ۔" عام طور پر، صفیں JVM جادو کا تھوڑا سا ہیں، کیونکہ... صف کو اندرونی طور پر کس طرح تشکیل دیا گیا ہے یہ معلوم نہیں ہے اور یہ جاوا ورچوئل مشین کے اندر کہیں واقع ہے۔ کوئی بھی دلچسپی رکھنے والا اسٹیک اوور فلو پر جوابات پڑھ سکتا ہے: " جاوا میں صف کی کلاس کیسے کام کرتی ہے؟ " اس سے پتہ چلتا ہے کہ اگر ہم ایک صف استعمال نہیں کر رہے ہیں، تو ہمیں کوئی ایسی چیز استعمال کرنی چاہیے جو لاگو کرے Iterable ۔ مثال کے طور پر:
List<String> names = Arrays.asList("John", "Sara", "Jack");
for (String name : names) {
	System.out.println("Name = " + name);
}
یہاں آپ صرف یہ یاد رکھ سکتے ہیں کہ اگر ہم مجموعے ( java.util.Collection ) استعمال کرتے ہیں تو اس کی بدولت ہمیں بالکل Iterable ملتا ہے ۔ اگر کسی آبجیکٹ میں ایک کلاس ہے جو Iterable کو لاگو کرتی ہے، تو اسے فراہم کرنے کا پابند ہے، جب iterator طریقہ کہا جاتا ہے، ایک Iterator جو اس آبجیکٹ کے مندرجات پر اعادہ کرے گا۔ مندرجہ بالا کوڈ میں، مثال کے طور پر، ایک بائیک کوڈ کچھ اس طرح ہوگا (انٹیلی جے آئیڈیا میں آپ "دیکھیں" -> "بائی کوڈ دکھائیں" کر سکتے ہیں:
کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کس طرح دہرایا، اعادہ کیا، لیکن اعادہ نہیں کیا - 5
جیسا کہ آپ دیکھ سکتے ہیں، ایک تکرار کرنے والا دراصل استعمال ہوتا ہے۔ اگر یہ ہر ایک لوپ کے لیے نہ ہوتا تو ہمیں کچھ ایسا لکھنا پڑتا:
List<String> names = Arrays.asList("John", "Sara", "Jack");
for (Iterator i = names.iterator(); /* continue if */ i.hasNext(); /* skip increment */) {
	String name = (String) i.next();
	System.out.println("Name = " + name);
}

تکرار کرنے والا

جیسا کہ ہم نے اوپر دیکھا، Iterable انٹرفیس کہتا ہے کہ کسی چیز کی مثالوں کے لیے، آپ کو ایک ایٹریٹر مل سکتا ہے جس کے ساتھ آپ مواد کو دوبارہ کر سکتے ہیں۔ ایک بار پھر، اسے SOLID سے واحد ذمہ داری کا اصول کہا جا سکتا ہے ۔ ڈیٹا کے ڈھانچے کو خود ٹراورسل نہیں چلانا چاہئے، لیکن یہ ایک ایسا فراہم کر سکتا ہے جو ہونا چاہئے۔ Iterator کا بنیادی نفاذ یہ ہے کہ اسے عام طور پر اندرونی طبقے کے طور پر قرار دیا جاتا ہے جو بیرونی طبقے کے مواد تک رسائی رکھتا ہے اور بیرونی طبقے میں موجود مطلوبہ عنصر فراہم کرتا ہے۔ یہاں کلاس کی ایک مثال ہے ArrayListکہ ایک تکرار کنندہ عنصر کو کیسے لوٹاتا ہے:
public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
}
ArrayList.thisجیسا کہ ہم دیکھ سکتے ہیں، ایٹریٹر کی مدد سے بیرونی کلاس اور اس کے متغیر تک رسائی حاصل کرتا ہے elementData، اور پھر وہاں سے ایک عنصر واپس کرتا ہے۔ لہذا، ایک تکرار کرنے والا حاصل کرنا بہت آسان ہے:
List<String> names = Arrays.asList("John", "Sara", "Jack");
Iterator<String> iterator = names.iterator();
اس کا کام اس حقیقت پر آتا ہے کہ ہم چیک کر سکتے ہیں کہ آیا مزید عناصر موجود ہیں ( hasNext طریقہ )، اگلا عنصر حاصل کریں ( اگلا طریقہ ) اور ہٹانے کا طریقہ، جو اگلے کے ذریعے موصول ہونے والے آخری عنصر کو ہٹاتا ہے ۔ ہٹانے کا طریقہ اختیاری ہے اور اس کے نفاذ کی ضمانت نہیں ہے۔ درحقیقت، جیسا کہ جاوا تیار ہوتا ہے، انٹرفیس بھی تیار ہوتے ہیں۔ لہذا، جاوا 8 میں ایک طریقہ بھی تھا forEachRemainingجو آپ کو باقی عناصر پر کچھ کارروائی کرنے کی اجازت دیتا ہے جو تکرار کرنے والے کے ذریعہ نہیں گئے تھے۔ تکرار کرنے والے اور مجموعوں کے بارے میں کیا دلچسپ ہے؟ مثال کے طور پر، ایک کلاس ہے AbstractList. ArrayListیہ ایک تجریدی کلاس ہے جو اور کا والدین ہے LinkedList۔ اور یہ ہمارے لیے دلچسپ ہے modCount جیسے فیلڈ کی وجہ سے ۔ ہر تبدیلی سے فہرست کے مواد میں تبدیلی آتی ہے۔ تو اس سے ہمیں کیا فرق پڑتا ہے؟ اور حقیقت یہ ہے کہ تکرار کنندہ اس بات کو یقینی بناتا ہے کہ آپریشن کے دوران وہ مجموعہ جس پر اسے دہرایا جاتا ہے تبدیل نہیں ہوتا ہے۔ جیسا کہ آپ سمجھتے ہیں، فہرستوں کے لیے ایٹریٹر کا نفاذ اسی جگہ پر ہے جس میں modcount ، یعنی کلاس میں AbstractList۔ آئیے ایک سادہ مثال دیکھیں:
List<String> names = Arrays.asList("John", "Sara", "Jack");
names = new ArrayList(names);
Iterator<String> iterator = names.iterator();
names.add("modcount++");
System.out.println(iterator.next());
یہاں پہلی دلچسپ بات ہے، اگرچہ موضوع پر نہیں۔ اصل میں Arrays.asListاپنا ایک خاص ArrayList( java.util.Arrays.ArrayList ) لوٹاتا ہے۔ یہ شامل کرنے کے طریقوں کو نافذ نہیں کرتا ہے، لہذا یہ ناقابل ترمیم ہے۔ اس کے بارے میں JavaDoc میں لکھا گیا ہے: fixed-size ۔ لیکن حقیقت میں، یہ مقررہ سائز سے زیادہ ہے ۔ یہ بھی ناقابل تغیر ہے ، یعنی ناقابل تبدیلی؛ ہٹانا بھی اس پر کام نہیں کرے گا۔ ہمیں بھی غلطی ہو جائے گی، کیونکہ... ایٹریٹر بنانے کے بعد، ہمیں اس میں modcount یاد آیا ۔ پھر ہم نے مجموعہ کی حالت کو "بیرونی طور پر" تبدیل کیا (یعنی تکرار کرنے والے کے ذریعے نہیں) اور تکرار کرنے والا طریقہ کار انجام دیا۔ لہذا، ہمیں غلطی ملتی ہے: java.util.ConcurrentModificationException ۔ اس سے بچنے کے لیے، تکرار کے دوران تبدیلی خود تکرار کرنے والے کے ذریعے کی جانی چاہیے، نہ کہ مجموعہ تک رسائی کے ذریعے:
List<String> names = Arrays.asList("John", "Sara", "Jack");
names = new ArrayList(names);
Iterator<String> iterator = names.iterator();
iterator.next();
iterator.remove();
System.out.println(iterator.next());
جیسا کہ آپ سمجھتے ہیں، اگر iterator.remove()آپ اسے پہلے نہیں کرتے ہیں iterator.next()، تو پھر کیونکہ۔ تکرار کرنے والا کسی بھی عنصر کی طرف اشارہ نہیں کرتا ہے، پھر ہمیں ایک غلطی ملے گی۔ مثال میں، تکرار کرنے والا جان عنصر پر جائے گا ، اسے ہٹائے گا، اور پھر سارا عنصر حاصل کرے گا ۔ اور یہاں سب کچھ ٹھیک ہو جائے گا، لیکن بد قسمتی، پھر "باریکیاں" ہیں) java.util.ConcurrentModificationException تب ہی واقع ہو گا جب hasNext()یہ درست ہو جائے گا ۔ یعنی، اگر آپ مجموعہ کے ذریعے ہی آخری عنصر کو حذف کرتے ہیں، تو تکرار کرنے والا نہیں گرے گا۔ مزید تفصیلات کے لیے، " #ITsubbotnik سیکشن JAVA: Java puzzles " سے جاوا پزل کے بارے میں رپورٹ دیکھنا بہتر ہے ۔ ہم نے اتنی تفصیلی گفتگو اس سادہ وجہ سے شروع کی کہ بالکل وہی باریکیاں لاگو ہوتی ہیں جب for each loop... ہمارا پسندیدہ تکرار کنندہ ہڈ کے نیچے استعمال ہوتا ہے۔ اور یہ تمام باریکیاں وہاں بھی لاگو ہوتی ہیں۔ صرف ایک چیز ہے، ہمیں تکرار کرنے والے تک رسائی حاصل نہیں ہوگی، اور ہم عنصر کو محفوظ طریقے سے ہٹانے کے قابل نہیں ہوں گے۔ ویسے، جیسا کہ آپ سمجھ رہے ہیں، ریاست اس وقت یاد رہتی ہے جب تکرار کرنے والا بنتا ہے۔ اور محفوظ حذف صرف کام کرتا ہے جہاں اسے کہا جاتا ہے۔ یعنی یہ آپشن کام نہیں کرے گا:
Iterator<String> iterator1 = names.iterator();
Iterator<String> iterator2 = names.iterator();
iterator1.next();
iterator1.remove();
System.out.println(iterator2.next());
کیونکہ iterator2 کے لیے iterator1 کے ذریعے ڈیلیٹ کرنا "بیرونی" تھا، یعنی یہ کہیں باہر کیا گیا تھا اور وہ اس کے بارے میں کچھ نہیں جانتا تھا۔ تکرار کرنے والوں کے موضوع پر، میں یہ بھی نوٹ کرنا چاہوں گا۔ انٹرفیس کے نفاذ کے لیے ایک خصوصی، توسیعی تکرار کرنے والا خاص طور پر بنایا گیا تھا List۔ اور انہوں نے اس کا نام رکھا ListIterator۔ یہ آپ کو نہ صرف آگے بڑھنے کی اجازت دیتا ہے، بلکہ پیچھے کی طرف بھی، اور آپ کو پچھلے عنصر اور اگلے عنصر کا انڈیکس معلوم کرنے کی بھی اجازت دیتا ہے۔ اس کے علاوہ، یہ آپ کو موجودہ عنصر کو تبدیل کرنے یا موجودہ ایٹریٹر پوزیشن اور اگلے ایک کے درمیان پوزیشن پر ایک نیا داخل کرنے کی اجازت دیتا ہے۔ جیسا کہ آپ نے اندازہ لگایا ہے، ListIteratorاسے ایسا کرنے کی اجازت ہے کیونکہ Listانڈیکس کے ذریعے رسائی نافذ ہے۔
کے لیے اور ہر ایک لوپ کے لیے: ایک کہانی کہ میں نے کیسے دہرایا، دہرایا، لیکن اعادہ نہیں کیا - 6

جاوا 8 اور تکرار

جاوا 8 کی ریلیز نے بہت سے لوگوں کی زندگی کو آسان بنا دیا ہے۔ ہم نے اشیاء کے مواد پر تکرار کو بھی نظر انداز نہیں کیا۔ یہ سمجھنے کے لیے کہ یہ کیسے کام کرتا ہے، آپ کو اس کے بارے میں کچھ الفاظ کہنے کی ضرورت ہے۔ Java 8 نے java.util.function.Consumer کلاس متعارف کرایا ۔ یہاں ایک مثال ہے:
Consumer consumer = new Consumer() {
	@Override
	public void accept(Object o) {
		System.out.println(o);
	}
};
کنزیومر ایک فنکشنل انٹرفیس ہے، جس کا مطلب ہے کہ انٹرفیس کے اندر صرف 1 غیر لاگو تجریدی طریقہ ہے جس کے لیے ان کلاسوں میں لازمی عمل درآمد کی ضرورت ہوتی ہے جو اس انٹرفیس کے آلات کی وضاحت کرتے ہیں۔ یہ آپ کو لیمبڈا جیسی جادوئی چیز استعمال کرنے کی اجازت دیتا ہے۔ یہ مضمون اس کے بارے میں نہیں ہے، لیکن ہمیں یہ سمجھنے کی ضرورت ہے کہ ہم اسے کیوں استعمال کر سکتے ہیں۔ لہذا، lambdas کا استعمال کرتے ہوئے، مندرجہ بالا کنزیومر کو اس طرح دوبارہ لکھا جا سکتا ہے: Consumer consumer = (obj) -> System.out.println(obj); اس کا مطلب یہ ہے کہ جاوا دیکھتا ہے کہ obj نامی کوئی چیز ان پٹ کو بھیجی جائے گی، اور پھر اس obj کے لیے اظہار -> کے بعد کیا جائے گا۔ تکرار کے طور پر، ہم اب یہ کر سکتے ہیں:
List<String> names = Arrays.asList("John", "Sara", "Jack");
Consumer consumer = (obj) -> System.out.println(obj);
names.forEach(consumer);
اگر آپ طریقہ پر جائیں تو forEachآپ دیکھیں گے کہ سب کچھ پاگل سادہ ہے۔ ہمارا پسندیدہ ہے for-each loop:
default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
}
ایٹریٹر کا استعمال کرتے ہوئے کسی عنصر کو خوبصورتی سے ہٹانا بھی ممکن ہے، مثال کے طور پر:
List<String> names = Arrays.asList("John", "Sara", "Jack");
names = new ArrayList(names);
Predicate predicate = (obj) -> obj.equals("John");
names.removeIf(predicate);
اس صورت میں، removeIf طریقہ ان پٹ کے بطور Consumer نہیں ، بلکہ ایک Predicate لیتا ہے ۔ یہ بولین لوٹاتا ہے ۔ اس صورت میں، اگر پیشین گوئی " سچ " کہتی ہے، تو عنصر کو ہٹا دیا جائے گا۔ یہ دلچسپ ہے کہ یہاں بھی سب کچھ واضح نہیں ہے)) ٹھیک ہے، آپ کیا چاہتے ہیں؟ کانفرنس میں پہیلیاں بنانے کے لیے لوگوں کو جگہ دینے کی ضرورت ہے۔ مثال کے طور پر، آئیے ہر اس چیز کو حذف کرنے کے لیے درج ذیل کوڈ لیں جس تک تکرار کرنے والا کچھ تکرار کے بعد پہنچ سکتا ہے۔
List<String> names = Arrays.asList("John", "Sara", "Jack");
names = new ArrayList(names);
Iterator<String> iterator = names.iterator();
iterator.next(); // Курсор на John
while (iterator.hasNext()) {
    iterator.next(); // Следующий элемент
    iterator.remove(); // Удалor его
}
System.out.println(names);
ٹھیک ہے، یہاں سب کچھ کام کرتا ہے۔ لیکن ہمیں یاد ہے کہ جاوا 8 آخر کار۔ لہذا، آئیے کوڈ کو آسان بنانے کی کوشش کریں:
List<String> names = Arrays.asList("John", "Sara", "Jack");
names = new ArrayList(names);
Iterator<String> iterator = names.iterator();
iterator.next(); // Курсор на John
iterator.forEachRemaining(obj -> iterator.remove());
System.out.println(names);
کیا یہ واقعی زیادہ خوبصورت ہو گیا ہے؟ تاہم، ایک java.lang.IllegalStateException ہوگا ۔ اور اس کی وجہ جاوا میں ایک بگ ہے۔ پتہ چلا کہ یہ طے شدہ ہے، لیکن JDK 9 میں۔ یہاں OpenJDK میں کام کا ایک لنک ہے: Iterator.forEachRemaining vs. Iterator.remove . قدرتی طور پر، اس پر پہلے ہی بات ہو چکی ہے: کیوں iterator.forEachRemaining کنزیومر لیمبڈا میں عنصر کو نہیں ہٹاتا؟ ٹھیک ہے، دوسرا طریقہ براہ راست Stream API کے ذریعے ہے:
List<String> names = new ArrayList(Arrays.asList("John", "Sara", "Jack"));
Stream<String> stream = names.stream();
stream.forEach(obj -> System.out.println(obj));

نتائج

جیسا کہ ہم نے اوپر کے تمام مواد سے دیکھا، ایک لوپ for-each loopایک تکرار کرنے والے کے اوپر صرف "نحوی شوگر" ہے۔ تاہم اب یہ کئی جگہوں پر استعمال ہوتا ہے۔ اس کے علاوہ، کسی بھی مصنوعات کو احتیاط کے ساتھ استعمال کیا جانا چاہئے. مثال کے طور پر، ایک بے ضرر شخص forEachRemainingناخوشگوار حیرت کو چھپا سکتا ہے۔ اور یہ ایک بار پھر ثابت کرتا ہے کہ یونٹ ٹیسٹ کی ضرورت ہے۔ ایک اچھا ٹیسٹ آپ کے کوڈ میں اس طرح کے استعمال کے معاملے کی نشاندہی کرسکتا ہے۔ آپ اس موضوع پر کیا دیکھ/پڑھ سکتے ہیں: #ویاچسلاو
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION