JavaRush /جاوا بلاگ /Random-UR /جاوا 8 گائیڈ۔ 1 حصہ
ramhead
سطح

جاوا 8 گائیڈ۔ 1 حصہ

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

"جاوا ابھی بھی زندہ ہے - اور لوگ اسے سمجھنا شروع کر رہے ہیں۔"

جاوا 8 کے میرے تعارف میں خوش آمدید۔ یہ گائیڈ آپ کو زبان کی تمام نئی خصوصیات کے ذریعے قدم بہ قدم لے جائے گا۔ مختصر، سادہ کوڈ کی مثالوں کے ذریعے، آپ سیکھیں گے کہ انٹرفیس ڈیفالٹ طریقے ، لیمبڈا ایکسپریشنز ، حوالہ جات کے طریقے ، اور قابل تکرار تشریحات کو کیسے استعمال کیا جائے ۔ مضمون کے اختتام تک، آپ APIs میں تازہ ترین تبدیلیوں جیسے کہ اسٹریمز، فنکشن انٹرفیس، ایسوسی ایشن ایکسٹینشنز، اور نئی تاریخ API سے واقف ہوں گے۔ بورنگ متن کی کوئی دیواریں نہیں - صرف تبصرہ کردہ کوڈ کے ٹکڑوں کا ایک گروپ۔ لطف اٹھائیں!

انٹرفیس کے لیے پہلے سے طے شدہ طریقے

Java 8 ہمیں پہلے سے طے شدہ مطلوبہ الفاظ کے استعمال کے ذریعے انٹرفیس میں لاگو کیے گئے غیر تجریدی طریقوں کو شامل کرنے کی اجازت دیتا ہے ۔ اس خصوصیت کو توسیعی طریقوں کے نام سے بھی جانا جاتا ہے ۔ یہاں ہماری پہلی مثال ہے: خلاصہ طریقہ حساب interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } کے علاوہ ، فارمولا انٹرفیس ایک طے شدہ طریقہ sqrt کی بھی وضاحت کرتا ہے ۔ وہ کلاسز جو فارمولہ انٹرفیس کو نافذ کرتی ہیں وہ صرف خلاصہ کیلکولیشن کا طریقہ نافذ کرتی ہیں ۔ پہلے سے طے شدہ sqrt طریقہ کو براہ راست باکس سے باہر استعمال کیا جا سکتا ہے۔ فارمولہ آبجیکٹ کو ایک گمنام آبجیکٹ کے طور پر لاگو کیا جاتا ہے۔ کوڈ کافی متاثر کن ہے: کوڈ کی 6 لائنیں صرف sqrt(a * 100) کا حساب لگانے کے لیے ۔ جیسا کہ ہم اگلے حصے میں دیکھیں گے، جاوا 8 میں سنگل میتھڈ آبجیکٹ کو لاگو کرنے کا ایک زیادہ پرکشش طریقہ ہے۔ Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); } }; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0

لیمبڈا کے تاثرات

آئیے جاوا کے ابتدائی ورژن میں تاروں کی صف کو کس طرح ترتیب دیا جائے اس کی ایک سادہ مثال کے ساتھ شروع کریں: شماریاتی مددگار طریقہ Collections.sort دی گئی فہرست کے عناصر کو ترتیب دینے کے لیے ایک فہرست اور ایک موازنہ لیتا ہے ۔ جو اکثر ہوتا ہے وہ یہ ہے کہ آپ گمنام موازنہ تخلیق کرتے ہیں اور انہیں ترتیب دینے کے طریقوں پر منتقل کرتے ہیں۔ ہر وقت گمنام اشیاء بنانے کے بجائے، جاوا 8 آپ کو بہت کم نحو، لیمبڈا ایکسپریشنز استعمال کرنے کی صلاحیت فراہم کرتا ہے : جیسا کہ آپ دیکھ سکتے ہیں، کوڈ بہت چھوٹا اور پڑھنے میں آسان ہے۔ لیکن یہاں یہ اور بھی چھوٹا ہو جاتا ہے: ایک سطری طریقہ کے لیے، آپ {} گھوبگھرالی منحنی خطوط وحدانی اور واپسی کے مطلوبہ لفظ سے چھٹکارا پا سکتے ہیں ۔ لیکن یہ وہ جگہ ہے جہاں کوڈ اور بھی چھوٹا ہو جاتا ہے: جاوا کمپائلر پیرامیٹرز کی اقسام سے واقف ہے، لہذا آپ انہیں بھی چھوڑ سکتے ہیں۔ اب آئیے اس بات کی گہرائی میں غوطہ لگائیں کہ حقیقی زندگی میں لیمبڈا کے تاثرات کیسے استعمال کیے جا سکتے ہیں۔ List names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator () { @Override public int compare(String a, String b) { return b.compareTo(a); } }); Collections.sort(names, (String a, String b) -> { return b.compareTo(a); }); Collections.sort(names, (String a, String b) -> b.compareTo(a)); Collections.sort(names, (a, b) -> b.compareTo(a));

فنکشنل انٹرفیس

لیمبڈا ایکسپریشن جاوا ٹائپ سسٹم میں کیسے فٹ ہوتے ہیں؟ ہر لیمبڈا انٹرفیس کے ذریعہ بیان کردہ ایک دی گئی قسم سے مساوی ہے۔ اور نام نہاد فنکشنل انٹرفیس میں بالکل ایک اعلان کردہ تجریدی طریقہ ہونا چاہیے۔ دی گئی قسم کا ہر لیمبڈا اظہار اس تجریدی طریقہ سے مطابقت رکھتا ہے۔ چونکہ پہلے سے طے شدہ طریقے تجریدی طریقے نہیں ہیں، اس لیے آپ اپنے فنکشنل انٹرفیس میں پہلے سے طے شدہ طریقے شامل کرنے کے لیے آزاد ہیں۔ ہم ایک صوابدیدی انٹرفیس کو لیمبڈا اظہار کے طور پر استعمال کر سکتے ہیں، بشرطیکہ انٹرفیس میں صرف ایک خلاصہ طریقہ ہو۔ اس بات کو یقینی بنانے کے لیے کہ آپ کا انٹرفیس ان شرائط کو پورا کرتا ہے، آپ کو @FunctionalInterface تشریح شامل کرنا چاہیے ۔ مرتب کرنے والے کو اس تشریح کے ذریعے مطلع کیا جائے گا کہ انٹرفیس میں صرف ایک طریقہ ہونا چاہیے، اور اگر اسے اس انٹرفیس میں ایک دوسرے تجریدی طریقہ کا سامنا کرنا پڑتا ہے، تو یہ ایک غلطی پھینک دے گا۔ مثال: ذہن میں رکھیں کہ یہ کوڈ بھی درست ہوگا یہاں تک کہ اگر @FunctionalInterface تشریح کا اعلان نہ کیا گیا ہو۔ @FunctionalInterface interface Converter { T convert(F from); } Converter converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123

طریقوں اور تعمیر کنندگان کے حوالے

اوپر دی گئی مثال کو شماریاتی طریقہ کا حوالہ استعمال کرتے ہوئے مزید آسان بنایا جا سکتا ہے: Java 8 آپ کو :: مطلوبہ الفاظ کی علامتوں کا استعمال کرتے ہوئے طریقوں اور تعمیر کنندگان کے حوالہ جات پاس کرنے کی اجازت دیتا ہے ۔ مندرجہ بالا مثال سے پتہ چلتا ہے کہ شماریاتی طریقے کیسے استعمال کیے جا سکتے ہیں۔ لیکن ہم اشیاء پر طریقوں کا حوالہ بھی دے سکتے ہیں: آئیے اس پر ایک نظر ڈالیں کہ :: کنسٹرکٹرز کے لیے کیسے کام کرتا ہے۔ سب سے پہلے، آئیے مختلف کنسٹرکٹرز کے ساتھ ایک مثال کی وضاحت کریں: اگلا، ہم نئی پرسن اشیاء بنانے کے لیے PersonFactory فیکٹری انٹرفیس کی وضاحت کرتے ہیں : Converter converter = Integer::valueOf; Integer converted = converter.convert("123"); System.out.println(converted); // 123 class Something { String startsWith(String s) { return String.valueOf(s.charAt(0)); } } Something something = new Something(); Converter converter = something::startsWith; String converted = converter.convert("Java"); System.out.println(converted); // "J" class Person { String firstName; String lastName; Person() {} Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } } interface PersonFactory

{ P create(String firstName, String lastName); } فیکٹری کو دستی طور پر لاگو کرنے کے بجائے، ہم کنسٹرکٹر حوالہ کا استعمال کرتے ہوئے ہر چیز کو ایک ساتھ باندھ دیتے ہیں: ہم Person::new کے ذریعے پرسن کلاس کے کنسٹرکٹر کا حوالہ بناتے ہیں ۔ جاوا کمپائلر کنسٹرکٹرز کے دستخط کا PersonFactory.create طریقہ کے دستخط کے ساتھ موازنہ کرکے مناسب کنسٹرکٹر کو خود بخود کال کرے گا ۔ PersonFactory personFactory = Person::new; Person person = personFactory.create("Peter", "Parker");

لیمبڈا علاقہ

لیمبڈا ایکسپریشنز سے بیرونی دائرہ کار کے متغیرات تک رسائی کو منظم کرنا کسی گمنام شے سے رسائی کے مترادف ہے۔ آپ مقامی دائرہ کار کے ساتھ ساتھ مثال کے فیلڈز اور مجموعی متغیرات سے حتمی متغیرات تک رسائی حاصل کر سکتے ہیں۔
مقامی متغیرات تک رسائی حاصل کرنا
ہم لامبڈا اظہار کے دائرہ کار سے حتمی ترمیم کرنے والے کے ساتھ مقامی متغیر کو پڑھ سکتے ہیں : لیکن گمنام اشیاء کے برعکس، متغیر کو لامبڈا اظہار سے قابل رسائی ہونے کے لیے حتمی قرار دینے کی ضرورت نہیں ہے ۔ یہ کوڈ بھی درست ہے: تاہم، نمبر متغیر کو ناقابل تغیر رہنا چاہیے، یعنی کوڈ کی تالیف کے لیے مضمر حتمی ہونا۔ درج ذیل کوڈ کو مرتب نہیں کیا جائے گا: لیمبڈا اظہار کے اندر نمبر میں تبدیلی کی بھی اجازت نہیں ہے۔ final int num = 1; Converter stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3 int num = 1; Converter stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3 int num = 1; Converter stringConverter = (from) -> String.valueOf(from + num); num = 3;
مثال کے شعبوں اور شماریاتی متغیرات تک رسائی
مقامی متغیرات کے برعکس، ہم لیمبڈا اظہار کے اندر مثال کے شعبوں اور شماریاتی متغیرات کو پڑھ اور ان میں ترمیم کر سکتے ہیں۔ ہم اس رویے کو گمنام اشیاء سے جانتے ہیں۔ class Lambda4 { static int outerStaticNum; int outerNum; void testScopes() { Converter stringConverter1 = (from) -> { outerNum = 23; return String.valueOf(from); }; Converter stringConverter2 = (from) -> { outerStaticNum = 72; return String.valueOf(from); }; } }
انٹرفیس کے پہلے سے طے شدہ طریقوں تک رسائی
پہلے حصے سے فارمولہ مثال کے ساتھ مثال یاد رکھیں ؟ فارمولا انٹرفیس پہلے سے طے شدہ sqrt طریقہ کی وضاحت کرتا ہے جس تک فارمولہ کی ہر مثال سے رسائی حاصل کی جا سکتی ہے ، بشمول گمنام اشیاء۔ یہ لیمبڈا اظہار کے ساتھ کام نہیں کرتا ہے۔ لیمبڈا اظہار کے اندر پہلے سے طے شدہ طریقوں تک رسائی حاصل نہیں کی جاسکتی ہے۔ درج ذیل کوڈ مرتب نہیں ہوتا ہے۔ Formula formula = (a) -> sqrt( a * 100);

بلٹ ان فنکشنل انٹرفیس

JDK 1.8 API بہت سے بلٹ ان فنکشنل انٹرفیس پر مشتمل ہے۔ ان میں سے کچھ جاوا کے پچھلے ورژن سے مشہور ہیں۔ مثال کے طور پر Comparator یا Runnable ۔ ان انٹرفیس کو @FunctionalInterface تشریح کا استعمال کرتے ہوئے lambda سپورٹ کو شامل کرنے کے لیے بڑھایا گیا ہے ۔ لیکن Java 8 API نئے فنکشنل انٹرفیس سے بھی بھرا ہوا ہے جو آپ کی زندگی کو آسان بنا دے گا۔ ان میں سے کچھ انٹرفیس گوگل کی امرود لائبریری سے مشہور ہیں ۔ یہاں تک کہ اگر آپ اس لائبریری سے واقف ہیں، تو آپ کو کچھ مفید توسیعی طریقوں کے ساتھ ان انٹرفیس کو کس طرح بڑھایا جاتا ہے اس پر گہری نظر ڈالنی چاہیے۔
پیش گوئیاں کرتا ہے۔
Predicates ایک دلیل کے ساتھ بولین فنکشنز ہیں۔ انٹرفیس میں پیشین گوئی کا استعمال کرتے ہوئے پیچیدہ منطقی تاثرات (اور، یا، نفی) بنانے کے لیے مختلف ڈیفالٹ طریقے شامل ہیں۔ Predicate predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false Predicate nonNull = Objects::nonNull; Predicate isNull = Objects::isNull; Predicate isEmpty = String::isEmpty; Predicate isNotEmpty = isEmpty.negate();
افعال
افعال ایک دلیل لیتے ہیں اور نتیجہ پیدا کرتے ہیں۔ پہلے سے طے شدہ طریقوں کا استعمال کئی فنکشنز کو ایک زنجیر میں اکٹھا کرنے کے لیے کیا جا سکتا ہے (کمپوز، اور پھر)۔ Function toInteger = Integer::valueOf; Function backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123"
سپلائرز
سپلائرز ایک یا دوسری قسم کا نتیجہ (مثال) واپس کرتے ہیں۔ افعال کے برعکس، فراہم کرنے والے دلائل نہیں لیتے ہیں۔ Supplier personSupplier = Person::new; personSupplier.get(); // new Person
صارفین
صارفین ایک ہی دلیل کے ساتھ انٹرفیس کے طریقوں کی نمائندگی کرتے ہیں۔ Consumer greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker"));
موازنہ کرنے والے
موازنہ کرنے والے ہمیں جاوا کے پچھلے ورژن سے جانتے ہیں۔ جاوا 8 آپ کو انٹرفیس میں مختلف ڈیفالٹ طریقے شامل کرنے کی اجازت دیتا ہے۔ Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0
اختیاری
Optionals انٹرفیس فعال نہیں ہے، لیکن NullPointerException کو روکنے کے لیے یہ ایک بہترین افادیت ہے ۔ یہ اگلے حصے کے لیے ایک اہم نکتہ ہے، تو آئیے ایک سرسری نظر ڈالتے ہیں کہ یہ انٹرفیس کیسے کام کرتا ہے۔ اختیاری انٹرفیس اقدار کے لیے ایک سادہ کنٹینر ہے جو کہ null یا غیر null ہو سکتا ہے۔ تصور کریں کہ کوئی طریقہ قیمت یا کچھ بھی نہیں لوٹا سکتا ہے۔ جاوا 8 میں، null واپس کرنے کے بجائے ، آپ ایک اختیاری مثال واپس کرتے ہیں ۔ Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0

ندی

java.util.Stream عناصر کا ایک سلسلہ ہے جس پر ایک یا بہت سے آپریشن کیے جاتے ہیں۔ ہر سٹریم آپریشن یا تو انٹرمیڈیٹ یا ٹرمینل ہوتا ہے۔ ٹرمینل آپریشنز ایک مخصوص قسم کے نتیجے میں واپس آتے ہیں، جب کہ انٹرمیڈیٹ آپریشنز اسٹریم آبجیکٹ کو خود ہی واپس کرتے ہیں، جس سے میتھڈ کالز کا سلسلہ بنایا جا سکتا ہے۔ سٹریم ایک انٹرفیس ہے، جیسے java.util.Collection فہرستوں اور سیٹوں کے لیے (نقشے تعاون یافتہ نہیں ہیں۔) ہر سٹریم آپریشن کو ترتیب وار یا متوازی طور پر انجام دیا جا سکتا ہے۔ آئیے اس پر ایک نظر ڈالتے ہیں کہ سلسلہ کیسے کام کرتا ہے۔ سب سے پہلے، ہم سٹرنگز کی فہرست کی شکل میں نمونہ کوڈ بنائیں گے: جاوا 8 میں کلیکشنز کو بہتر بنایا گیا ہے تاکہ آپ Collection.stream() یا Collection.parallelStream() کو کال کر کے آسانی سے سٹریمز بنا سکیں ۔ اگلا حصہ سب سے اہم، سادہ سٹریم آپریشنز کی وضاحت کرے گا۔ List stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1");
فلٹر
فلٹر سٹریم کے تمام عناصر کو فلٹر کرنے کے لیے پیش گوئیاں قبول کرتا ہے۔ یہ آپریشن انٹرمیڈیٹ ہے، جو ہمیں دوسرے سٹریم آپریشنز کو کال کرنے کی اجازت دیتا ہے (مثال کے طور پر ہر ایک کے لیے) نتیجے میں آنے والے (فلٹرڈ) نتیجے پر۔ ForEach ایک آپریشن کو قبول کرتا ہے جو پہلے سے فلٹر شدہ سٹریم کے ہر عنصر پر کیا جائے گا۔ ForEach ایک ٹرمینل آپریشن ہے۔ مزید، دوسرے آپریشنز کو کال کرنا ناممکن ہے۔ stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa2", "aaa1"
چھانٹی ہوئی
ترتیب شدہ ایک انٹرمیڈیٹ آپریشن ہے جو سلسلہ کی ترتیب شدہ نمائندگی لوٹاتا ہے۔ عناصر کو صحیح ترتیب میں ترتیب دیا جاتا ہے جب تک کہ آپ اپنے Comparator کی وضاحت نہ کریں ۔ stringCollection .stream() .sorted() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa1", "aaa2" اس بات کو ذہن میں رکھیں کہ sorted خود مجموعہ کو متاثر کیے بغیر سلسلہ کی ایک ترتیب شدہ نمائندگی تخلیق کرتا ہے۔ stringCollection عناصر کی ترتیب اچھوتی رہتی ہے: System.out.println(stringCollection); // ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1
نقشہ
انٹرمیڈیٹ میپ آپریشن نتیجے میں آنے والے فنکشن کا استعمال کرتے ہوئے ہر عنصر کو کسی اور شے میں تبدیل کرتا ہے۔ مندرجہ ذیل مثال ہر اسٹرنگ کو ایک بڑے سٹرنگ میں تبدیل کرتی ہے۔ لیکن آپ ہر چیز کو مختلف قسم میں تبدیل کرنے کے لیے نقشہ بھی استعمال کر سکتے ہیں۔ نتیجے میں آنے والے سٹریم آبجیکٹ کی قسم اس فنکشن کی قسم پر منحصر ہے جسے آپ نقشے پر منتقل کرتے ہیں۔ stringCollection .stream() .map(String::toUpperCase) .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println); // "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"
میچ
سٹریم ریلیشن میں کسی خاص پیشین گوئی کی سچائی کو جانچنے کے لیے مختلف مماثل آپریشنز کا استعمال کیا جا سکتا ہے۔ تمام میچ آپریشنز ٹرمینل ہیں اور بولین نتیجہ واپس کرتے ہیں۔ boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a")); System.out.println(anyStartsWithA); // true boolean allStartsWithA = stringCollection .stream() .allMatch((s) -> s.startsWith("a")); System.out.println(allStartsWithA); // false boolean noneStartsWithZ = stringCollection .stream() .noneMatch((s) -> s.startsWith("z")); System.out.println(noneStartsWithZ); // true
شمار
شمار ایک ٹرمینل آپریشن ہے جو سٹریم کے عناصر کی تعداد کو لمبے کے طور پر لوٹاتا ہے ۔ long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3
کم
یہ ایک ٹرمینل آپریشن ہے جو پاس کردہ فنکشن کا استعمال کرتے ہوئے اسٹریم کے عناصر کو مختصر کرتا ہے۔ نتیجہ ایک اختیاری ہو گا جس میں مختصر قدر ہو گی۔ Optional reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); // "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"

متوازی سلسلے

جیسا کہ اوپر ذکر کیا گیا ہے، سلسلے ترتیب وار یا متوازی ہو سکتے ہیں۔ سلسلہ وار سٹریم آپریشنز ایک سیریل تھریڈ پر کیے جاتے ہیں، جبکہ متوازی سٹریم آپریشنز متعدد متوازی دھاگوں پر کیے جاتے ہیں۔ مندرجہ ذیل مثال یہ ظاہر کرتی ہے کہ متوازی ندی کا استعمال کرتے ہوئے کارکردگی کو آسانی سے کیسے بڑھایا جائے۔ سب سے پہلے، آئیے منفرد عناصر کی ایک بڑی فہرست بنائیں: اب ہم اس مجموعہ کے سلسلے کو ترتیب دینے میں صرف ہونے والے وقت کا تعین کریں گے۔ int max = 1000000; List values = new ArrayList<>(max); for (int i = 0; i < max; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); }
سلسلہ وار سلسلہ
long t0 = System.nanoTime(); long count = values.stream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("sequential sort took: %d ms", millis)); // sequential sort took: 899 ms
متوازی ندی
long t0 = System.nanoTime(); long count = values.parallelStream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis)); // parallel sort took: 472 ms جیسا کہ آپ دیکھ سکتے ہیں، دونوں ٹکڑے تقریباً ایک جیسے ہیں، لیکن متوازی چھانٹنا 50% تیز ہے۔ آپ کو بس stream() کو parallelStream() میں تبدیل کرنے کی ضرورت ہے ۔

نقشہ

جیسا کہ پہلے ہی ذکر کیا گیا ہے، نقشے اسٹریمز کو سپورٹ نہیں کرتے ہیں۔ اس کے بجائے، نقشہ عام مسائل کے حل کے لیے نئے اور مفید طریقوں کی حمایت کرنے لگا۔ مندرجہ بالا کوڈ بدیہی ہونا چاہئے: putIfAbsent ہمیں اضافی null چیک لکھنے کے خلاف خبردار کرتا ہے۔ forEach نقشہ کی ہر قدر کے لیے ایک فنکشن کو قبول کرتا ہے۔ یہ مثال دکھاتی ہے کہ فنکشنز کا استعمال کرتے ہوئے نقشہ کی قدروں پر آپریشنز کیسے انجام پاتے ہیں: اگلا، ہم سیکھیں گے کہ کسی دی گئی کلید کے اندراج کو کیسے ہٹایا جائے صرف اس صورت میں جب وہ کسی دی گئی قدر سے نقشہ بناتی ہے: ایک اور اچھا طریقہ: نقشہ کے اندراجات کو ضم کرنا کافی آسان ہے: ضم کرنا یا تو نقشے میں کلید/قدر داخل کرے گا، اگر دی گئی کلید کے لیے کوئی اندراج نہیں ہے، یا مرج فنکشن کو کال کیا جائے گا، جو موجودہ اندراج کی قدر کو بدل دے گا۔ Map map = new HashMap<>(); for (int i = 0; i < 10; i++) { map.putIfAbsent(i, "val" + i); } map.forEach((id, val) -> System.out.println(val)); map.computeIfPresent(3, (num, val) -> val + num); map.get(3); // val33 map.computeIfPresent(9, (num, val) -> null); map.containsKey(9); // false map.computeIfAbsent(23, num -> "val" + num); map.containsKey(23); // true map.computeIfAbsent(3, num -> "bam"); map.get(3); // val33 map.remove(3, "val3"); map.get(3); // val33 map.remove(3, "val33"); map.get(3); // null map.getOrDefault(42, "not found"); // not found map.merge(9, "val9", (value, newValue) -> value.concat(newValue)); map.get(9); // val9 map.merge(9, "concat", (value, newValue) -> value.concat(newValue)); map.get(9); // val9concat
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION