-
قابلیت های جدید جاوا
در این تاپیک سعی می کنم قابلیت های جدید اضافه شده در جاوا ۸ رو قرار بدم. (با اجازه اساتید)
البته چیزایی که میگم اطلاعات خودم نیست و صرفا نتیجه ترجمست.
عبارت های لاندا
این قابلیت توی جاوا ۸ معرفی شد و می تونه سرعت کدنویسی رو چندبرابر کنه. فکر می کنم مهمترین قابلیت اضافه شده توی جاوا ۸ همین عبارات لاندا (Lambda Expressions) باشه.
قالب کلی این عبارت ها بصورت بدنه <- پارامترهای ورودی هستش.
برای نوشتن این عبارات قوانین زیر وجود داره:
- نوشتن نوع پارامترها اختیاریه.
- در صورت وجود یک پارامتر (و نه بیشتر) گذاشتن پرانتز دور پارامتر اختیاریه.
- در صورتی که بدنه ی عبارت لاندای شما تک خطی باشه گذاشتن آکولاد اطراف بدنه اختیاریه.
- نوشتن دستور return اختیاره، در صورتی که بدنه عبارت تک خطی باشه.
در زیر چند تا مثال برای آشنایی بیشتر می بینیم (مثال های خیلی بیشتری رو در اینترنت پیدا می کنین):
() -> System.out.println("Hello");
(String str) -> System.out.println(str);
str -> System.out.println(str);
حالا چندتا مثال کاربردی:
۱. مرتب سازی آرایه:
با یک عبارت لاندای ساده میشه یک آرایه رو به سادگی مرتب کرد (این کار رو با واسط Comparor انجام میدیم که یک نوع FunctionalInterface هست):
String someArray = new String[] {"AAA", "BB", "CCCC", "d"};
Arrays.sort(someArray,
(String s1, String s2) -> s2.length() - s1.length());
۲. برنامه نویسی چند نخی:
از حالا به بعد میشه عبارت های لاندا رو برای تعریف ریسمان های جدید هم استفاده کرد (واسط Runnable هم در جاوا ۸ یک Functional Interface شده):
public class Hello {
private Runnable r1 = () -> System.out.println("Hello! I'm R1");
private Runnable r2 = () -> System.out.println("Hello! I'm R2");
public static void main(String[] args) {
Hello hello = new Hello();
hello.r1.run();
hello.r2.run();
}
}
مثال های بیشتری رو در منابع اوراکل پیدا می کنید.
امیدوارم مفید بوده باشه. :چشمک:
موفق باشید.
-
نقل قول: قابلیت های جدید جاوا ۸
یعنی به جای اینتر فیس هم میشه لاندا بنویسیم ؟ اگه اینترفیس دوتا متد داشته باشه که پارامتر هاشون شبیه همه از کجا می فهمه کدوم لاندا جای کدوم متده؟
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
نوشته شده توسط
dasssnj
یعنی به جای اینتر فیس هم میشه لاندا بنویسیم ؟ اگه اینترفیس دوتا متد داشته باشه که پارامتر هاشون شبیه همه از کجا می فهمه کدوم لاندا جای کدوم متده؟
عبارات لاندا فقط می تونن جای functional interface بشینن. اینا در واقع اینترفیس هایی هستن که فقط یدونه abstract method دارن. بنابراین نمیشه برای interfaceهای با بیشتر از یه abstract متد استفادشون کرد و بی معنی هم هست این کار چون ابهام درست میکنه.
اگر چنین اینترفیسی داشته باشین (مثل MouseListener) باید ابتدا یه اینترفیس فرزند ازش درست کنید و همه متدهایی که نمیخواین رو جز اون یکی که میخواین default کنید!
بعد ازش استفاده کنید!
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
یعنی به جای اینتر فیس هم میشه لاندا بنویسیم ؟ اگه اینترفیس دوتا متد داشته باشه که پارامتر هاشون شبیه همه از کجا می فهمه کدوم لاندا جای کدوم متده؟
همونطور که cups_of_java عزیز گفتن، عبارات لاندا می تونن برای واسط هایی به کار برن که فقط یک متد Abstract دارن. اصولا اینجور واسط ها باید با اصلاحگر FunctionalInterface@ تعریف بشن. ولی به دلیل اینکه بتونیم از واسط های قدیمی تر (که با FunctionalInterface@ تعریف نشدن) همراه با عبارات لاندا استفاده کنیم، این کار اختیاریه و هر واسطی که فقط یک متد Abstract داشته باشه می تونه با یک عبارت لاندا تعریف و مقداردهی بشه. حتی ما خودمون هم می تونیم یک واسط بصورت FunctionalInterface بنویسیم. البته بهتره حتما قبلش واسط های بسته ی java.util.function رو چک کنیم تا دوباره کاری نکرده باشیم!
خب، در مورد عبارات لاندا باید یادمون باشه که برای اکثر حالات تنها کاری که می کنن راحتی، خوانایی و زیبایی کده. برای مثال در تکه کد زیر، r1 و r2 از دو روش متفاوت ولی یکسان تعریف شدن:
// Java 7:
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("I'm R1!");
}
};
// Java 8:
Runnable r2 = () -> System.out.println("I'm R2!");
اوراکل پیشنهاد کرده تا حد امکان از عبارات لاندا استفاده بشه (هرچند فکر کنم هر برنامه نویسی ترجیهش بده! :لبخند:)
یک مثال عملی تر:
بطور کلی به نظر می رسه، عبارت های لاندا خیلی خوب خودشون رو در کار با گروهی از داده ها (آرایه ها، ساختمان های داده، پرسش از دیتابیس و...) نشون میدن (هرچند این نظر شخصیمه).
برای نمونه، فرض کنید میخوایم تابعی بنویسیم که اعداد زوج از یک لیست رو واسمون جدا کنه و توی یه لیست جدید برگردونه. خب کار آسونه، تابع رو می نویسیم:
public static ArrayList<Integer> filter1(Collection<Integer> coll) {
ArrayList<Integer> result = new ArrayList<Integer>();
for (int i : coll) {
if (i % 2 == 0) {
result.add(i);
}
}
return result;
}
حالا اگه به لیست اعداد فرد هم نیاز داشتیم چی؟ خب مجبوریم دیگه! بنویسیم:
public static ArrayList<Integer> filter2(Collection<Integer> coll) {
ArrayList<Integer> result = new ArrayList<Integer>();
for (int i : coll) {
if (i % 2 != 0) {
result.add(i);
}
}
return result;
}
اگه اعداد مثبت رو هم خواستیم جدا کنیم چی؟!! اگه اعدادی مجذور کاملن رو خواستیم چی؟؟؟؟؟
خب خیلی راحت توی جاوا ۸، با واسط Predicate همه رو پشتیبانی می کنیم! اینجوری:
public static ArrayList<Integer> filter3(Collection<Integer> coll, Predicate<Integer> p) {
// اینم از قابلیت های جدید جاواست
ArrayList<Integer> result = new ArrayList<>();
for (int i : coll) {
if (p.test(i)) {
result.add(i);
}
}
return result;
}
حالا دیگه واسه جداسازی اعداد مثبت کافیه بنویسیم:
List<Integer> list = Arrays.asList(2, 8, 7, 12, 17, 23, 26, 31, 9, 11);
ArrayList<Integer> sublist = filter3(list, i -> i > 0);
sublist.forEach(i -> System.out.println(i));
حالا که تا اینجا اومدیم! بیاید توی تابع از یکی دیگه از قابلیت های جالب Java 8 به اسم Stream استفاده کنیم! اینجوری:
public static ArrayList<Integer> filter4(Collection<Integer> coll, Predicate<Integer> p) {
ArrayList<Integer> result = new ArrayList<>();
coll.stream().filter(p).forEach(i -> result.add(i));
return result;
}
دیگه فکر کنم واضح باشه طرز عملکردش...
ببخشید اگه طولانی شد.
اگه عمری بود به مسایل دیگه ای هم می پردازم. اساتید هم اگر ایرادی تو حرفام هست اصلاح کنن. :لبخندساده:
-
نقل قول: قابلیت های جدید جاوا ۸
واقعا ممنون .
ولی مشکل این کد چیه؟
public class New {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ali d = (e -> System.out::println);
}
@FunctionalInterface
interface ali {
public abstract void a(int e);
}
}
جاوا واقعا رو دست همه زبونا زده.
-
نقل قول: قابلیت های جدید جاوا ۸
این چیزی که شما نوشتین:یکی دیگه از قابلیت های جدید جاواست که اگه عمری بود در موردش حرف میزنم...
باید اینجوری نوشته بشه:
ali d = e -> System.out.println("Hello World!");
نقل قول:
جاوا واقعا رو دست همه زبونا زده.
نمیشه اینو گفت... مثلا عبارات لاندا زودتر در دات نت وجود داشتن... حتی در پایتون. ولی مثلا توی دات نت واسه اضافه شدن چنین قابلیتی مایکروسافت کلی جزییات به دات نت اضافه کرد! فقط چندتا Keyword مخصوص این عبارات تخصیص داد! امتیاز جاوا اینه که با حفظ سادگی و کمترین تغییرات یه قابلیت رو اضافه میکنه و در عین حال حفظ سبک هم میکنه.
در هر صورت قبول دارم کارای خوبی اوراکل انجام داده و بعضیاشونم تقریبا بی همتاست تو زبان های دیگه. من که واقعا با قابلیت های اضافه شده توی جاوا ۷ و مخصوصا جاوا ۸ خیلی حال کردم! البته توی برنامه هایی که نوشتم هم تاثیر داشت و فقط حال نبود! :لبخند:
-
نقل قول: قابلیت های جدید جاوا ۸
ممنون ولی من می خواستم از System.out::println استفاده کنم.
یعنی عدد e را با System.out::println چاپ کنم.
-
نقل قول: قابلیت های جدید جاوا ۸
آها. بله میشه کد شما رو با Method Refrence هم نوشت:
ali d = System.out::println;
-
نقل قول: قابلیت های جدید جاوا ۸
ممنون از این تاپیک فوق العاده
-
جلوگیری از سرریز بی موقع - متدهای Exact در Java
واقعا وقت نمیکنم بیام وگرنه حتماً این تاپیک رو کامل میکردم. امروزم یکی از قابلیتهای کوچیک جدید Java رو مطرح میکنم.
همیشه یکی از مشکلات برنامهنویسا توی عملیات ریاضی، سرریز دادههاست. کمابیش راهحلهایی براشون داریم هممون ولی Java اومده اینکار رو کمی سادهتر کرده. البته این راهحلش هنوز هم همهی مشکل رو حل نمیکنه ولی از انجام دادن دستی کارا راحتتره. توی نسحهی جدید Java چند متد برای محاسبهی دقیق (Exact) اضافه شده که در صورتی که سرریز رخ بده یه استثناء ArithmeticException ایجاد میکنه. اینم یه مثال:
long num1 = 1234567, num2 = 7654321;
try {
long mul = Math.multiplyExact(num1, num2);
} catch(ArithmeticException arex) {
System.out.println("Overflow! :(");
}
همچنین برای جمع و تفریق، قرینه کردن و افزایش و کاهش هم متدهایی با همین روش استفاده اضافه شده.
خوبی این روش اینه که جلوگیری میکنه از Overflowهای پیشبینی نشده. ولی دو تا ضعفم داره؛ اولاً یکم کارایی رو کاهش میده، واسه همین توی Processهای پرتکرار سفارش نمیشه، ثانیاً باید خودمون تشخیص بدیم چه جاهایی ممکنه سرریز رخ بده.
امیدوارم کمک بکنه بهتون. ایشالا اگه عمری باشه و وقت بشه در مورد Streamها که خیلی هم مفصلن و بدیع(!) هم حرف میزنم در آینده.
-
نقل قول: قابلیت های جدید جاوا ۸
سلام، پیشنهاد میکنم درباره monad های معروف مثل optional و maybe و promise و ... هم مطلب بذارید، خیلی جاها به درد میخورن.
-
نقل قول: قابلیت های جدید جاوا ۸
متاسفانه اوراکل خیلی هم در زمینه لامبدا خوب کار نکرده و جاوا 8 راه زیادی داره تا بشه برنامه های خوب فانکشنال باهاش نوشت . دیباگ برنامه هایی که با استفاده از لامبدا در جاوا 8 نوشته میشه به شدت سخته و معایبش بیشتر از مزایاشه
http://vanillajava.blogspot.com/2014/09/lambdas-and-side-effects.html
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
متاسفانه اوراکل خیلی هم در زمینه لامبدا خوب کار نکرده و جاوا 8 راه زیادی داره تا بشه برنامه های خوب فانکشنال باهاش نوشت . دیباگ برنامه هایی که با استفاده از لامبدا در جاوا 8 نوشته میشه به شدت سخته و معایبش بیشتر از مزایاشه
اولا مشکلات مطرح شده توی این وبلاگ کاملا هم صحیح نیستن، مثلا مشکل دومش که کاملا اشتباه گرفته شده و شما میتونی موقع تعریف یه عبارت Lambda کاملا نوع نهاییش رو تعیین کنی.
ولی حالا اگه نخوام به جزئیات بپردازم، اول باید بگم با اضافه شدن عبارات Lambda هیچوقت قرار نبوده Java به یه زبون برنامهنویسی Functional (چیزی مثل قابلیتهای دوستداشتنی Scala، Javascript، Go، FSharp، Python و...) تبدیل بشه. عبارات Lambda کمی جاوا رو به این زبونا نزدیک میکنه فقط.
در واقع هرچند مرز دقیقی بین Functional Programming و Object Oriented Programming وجود نداره ولی Java یه زبان شیءگراست و قرار نیست نوعش رو تغییر بده!
در ضمن عبارات Lambda صرفا مختص Java نیست. اتفاقا به نظر میاد Java خیلی دیر به یاد عبارات Lambda افتاد! قبلا 11 ++C، داتنت و... عبارات Lambda رو به خودشون اضافه کرده بودن. منم قبول دارم اضافه کردن این عبارات Debug رو سخت میکنه. اما هرچیزی بهایی داره. مشکل Debug توی فریمورکهای دیگهم دیده میشه. حتی به نظر من Java تلاش زیادی کرده Debug رو راحت کنه. مخصوصا در مورد چگونگی ذخیره عبارات Lambda توی حافظه خیلی از NET. جلوتره.
بهرحال نظر من اینه که هر چیزی نقاط قوت و ضعفی داره. این مشکلات اگر هم ۱۰۰٪ درست باشن توی فریمورکهای دیگه هم وجود دارن واساساً این نقاط ضعف مربوط به مفهوم عبارات Lambdaست! نه نحوهی پیاده سازیشون توی Java یا NET. یا هر فریمورک دیگهای.
مثلا برنامه نویسی شیءگرای کامل (مثل همین Java یا همون #C) هم علاوه بر فواید خیلی زیادش نقاط ضعفی داره برای خودش...
در مورد چیزایی که خیلی عالی میشد اگه Java به عبارات Lambda اضافه میکرد، من این موارد رو خیلی قبول دارم... هرچند شعار Java همیشه سادگی بوده و اینا باش در تضادن.
-
نقل قول: قابلیت های جدید جاوا ۸
سلام به مدیران تالار با احترام
در صورتی که اجازه میدن این تاپیک رو فعالتر کنیم یعنی از اونجایی که تقریبا سه سال و نیم که دیگه به روز نشده دلیل خاصی داره!!
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
نوشته شده توسط
farhad_shiri_ex
سلام به مدیران تالار با احترام
در صورتی که اجازه میدن این تاپیک رو فعالتر کنیم یعنی از اونجایی که تقریبا سه سال و نیم که دیگه به روز نشده دلیل خاصی داره!!
مدیران تقریبا نیستن. مطلبی در این باره دارید به اشتراک بگذارید همه استفاده کنیم
-
نقل قول: قابلیت های جدید جاوا ۸
public final DataObjectService.RecordsService<RecordsModelDao> recordsService = getNewInstance();
private Function<RecordsModelDao,Long> serviceRec = recordsService::insertRecordsRow;
public <DAO> Optional<DAO> getOptional(DAO value) {
return Optional.of(value);
}
private BiConsumer<RecordsModelDao,String> insertRec =
(rec,shamsiDate) -> getOptional(RecordsModelDao.getDaoRecordsDb(rec,sh amsiDate))
.ifPresent(recordsModelDao -> result[0] = serviceRec.apply(recordsModelDao));
استفاده از API FUNCTION در جاوا 8
Function
BiConsumer
Optional
-
نقل قول: قابلیت های جدید جاوا ۸
public final Supplier<DataBaseService> DATABASE_SERVICE;
DATABASE_SERVICE = this::getDBaseService;
استفاده از اینترفیس Supplier
-
نقل قول: قابلیت های جدید جاوا ۸
private class Str {
private Character startWith(String s) {
return s.charAt(0);
}
}
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
default T convert() {
return (T) "test";
}
}
private Str s = new Str();
Converter<String , Character> cc1 = v-> s.startWith(v);
Converter<String , Character> cc2 = s::startWith;
استفاده از Functional Interface , Method Reference
-
نقل قول: قابلیت های جدید جاوا ۸
دوستان عزیز در صورت هرگونه ابهام بفرمایید توضیح بدم.!
فقط از کتابخانه های جاوا 8 در اندروید SDK 24 به بعد می توان استفاده کرد قابل توجه دوستان اندرویدی .
-
نقل قول: قابلیت های جدید جاوا ۸
String st ;
boolean b ;
Predicate<String> notEmpty = (x) -> x.length() > 0;
Predicate<String> nonNull = (x) -> x != null;
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();
void test() {
b = notEmpty.test(st); //true
b = notEmpty.negate().test(st); //false
b = nonNull.and(notEmpty).test(st);
b = isEmpty.test(st);
b = isNotEmpty.test(st);
}
استفاده از اینترفیس فوق العاده Predicate
-
نقل قول: قابلیت های جدید جاوا ۸
private Function<String , Integer> toInteger = Integer::valueOf; //(s) -> Integer.valueOf(s);
private Function<String , String> bakStr = toInteger.andThen(String::valueOf); //(s) -> String.valueOf(s);
void test2() {
bakStr.apply("123");
}
تجمیع توابع با متد andThen اینترفیس Function
-
نقل قول: قابلیت های جدید جاوا ۸
اگر مفید فایده بود ادامه بدم.!
-
نقل قول: قابلیت های جدید جاوا ۸
بله چرا که نه. بعضیاشو ندیده بودم.
فقط یکم بیشتر توضیح بدید از هر کلاس یا اینترفیس جدیدی که معرفی میکنید. مثلا قبلا این امکان چطور بوده و الان چرا ساده تر شده و...
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
نوشته شده توسط
vahid-p
بله چرا که نه. بعضیاشو ندیده بودم.
فقط یکم بیشتر توضیح بدید از هر کلاس یا اینترفیس جدیدی که معرفی میکنید. مثلا قبلا این امکان چطور بوده و الان چرا ساده تر شده و...
باشه چشم سعی میکنم توضیحاتی که قابل استنباط باشه و در توانایی من باشه ارائه بدم.
بیشتر اینهایی رو که بیان کردم خودم زیاد استفاده کردم فکر کردم از زمانی که جاوا 8 اومده تقریبا کد نویسی تو جاوا خیلی تغییر کرده علی الخصوص تو فریم ورک Stream که تقریبا من خیلی شبیه تکنولوژی LINQ تو دات نت مبینمش و فوق العاده اس کد نویسی رو دگرگون کرده البته یکم هم گنگ تر شده!
من فکر میکنم یکی از دلایلی که خیلی رو این تغییرات جاوا 8 در این 4 - 5 سال گذشته برای ما برنامه نویس های ایرانی که نتونستیم خودمونو البته بیشتر خودم رو عرض میکنم آداپته کنیم اینه که تا اندروید SDK 24 از جاوا 8 تو فریم ورک های اندروید خبری نبود ماهم خیلی دنبال اش نبودیم.
ولی چشم سعی میکنم مثال هایی که خودم کار کردم و تست کردم با توضیح بذارم اگر هم کم وکاستی داره به هم کمک کنید هم من بهتر بشم وهم انشاالله برنام نویس های ایرانی که دارن زحمت میکشن و با اینهمه منابع مختلفی که هست هرکدومم یه سبک و استایل داره و شرایط گیج کننده بتونیم هرچه بهتر باشیم
-
نقل قول: قابلیت های جدید جاوا ۸
تا قیل جاوا 8 مطمئنا از شرطهای تدافعی برای چک کردن اشیاء NULL ویا از بلوک های TRY...CATCH...FINALLY استفاده میکردیم ولی با دستور زیر...
Predicate<Collection<E>> notNull = Objects::nonNull;
notNull.test(source);
به راحتی میتونیم خیلی از همون شرطها رو تجمیع کنیم ویا از دو شرط مساوی غیر مساوی ویا بهتر بگم از شرایط قانون دمورگان ویا شرکت پذیری (درس ساختمان داده) استفاده کنیم بدون اینکه بخواهیم شرطهای عجیب و غریب بنویسم مثل ..
private Predicate<CharSequence> isEmpty = TextUtils::isEmpty;
Predicate<CharSequence> isValid = isEmpty
.negate()
.and(inputEmailStr -> change);
if(isValid.test(value));
در تکه کد بالا گفتم اگر آبجکتی که از نوع CharSequence خالی باشه که از کلاس TextUtils استفاده کردم وبعد با متد negate() نقض اش کردم و با عبارت and(inputEmailStr -> change) با یه Perdicate دیگه تلفیق اش کردم و در نهایت عبارت با این متد تست میکنم if(isValid.test(value));
حالا اگر این اینترفیس نبود من این مینوشتم
if(!TextUtils.isEmpty((CharSequence) mUsername) && change);
شاید ساده به نظر بیاید ولی دیگه انعطاف نداره نمیتونم جای دیگه ازش استفاده کنم و بحث دوباره کاری و تکنیکهای برنامه نویسی و غیره پیش میاد.
به هر حال نحوه استفاده های زیادی داره که بسته به شرایط فرق میکنه.
-
نقل قول: قابلیت های جدید جاوا ۸
فکر کنید برای اینکه بخواهید یه مقدار ماکزیمم رو توی یه لیست پیوندی پیدا کنید چند خط کد باید بنویسیم حالا کاری به الگوریتم اش نداره که جستجوی خطی و یا باینری و یا ادغامی ویا سریع میتونه هرچی باشه ولی مطمئنا کدنویسی زیادی میخواد ولی با Stream چطوری میتونیم انجام اش بدیم ؟!
تابع زیر رو برای 20،000،000 رکورد تو یک لیست پیوندی تست کردم توی Core I5 64Bit زمان اجراش 100ml sec بود شگفت آور...
public <E extends Comparable<? super E>> E max(List<? extends E> list, boolean sorted) {
Stream<? extends E> stream = list.stream();
Optional<E> optional = stream
.sorted()
.collect(Collectors.maxBy((o1, o2) ->
sorted ? o1.compareTo(o2) == 1 ? 0 : 1
: o1.compareTo(o2)));
return optional.isPresent() ? optional.get() : list.get(0) ;
-
نقل قول: قابلیت های جدید جاوا ۸
فکر کنید برای اینکه بخواهید یه مقدار ماکزیمم رو توی یه لیست پیوندی پیدا کنید چند خط کد باید بنویسیم حالا کاری به الگوریتم اش نداره که جستجوی خطی و یا باینری و یا ادغامی ویا سریع میتونه هرچی باشه ولی مطمئنا کدنویسی زیادی میخواد ولی با Stream چطوری میتونیم انجام اش بدیم ؟!
تابع زیر رو برای 20،000،000 رکورد تو یک لیست پیوندی تست کردم توی Core I5 64Bit زمان اجراش 100ml sec بود شگفت آور...
public <E extends Comparable<? super E>> E max(List<? extends E> list, boolean sorted) {
Stream<? extends E> stream = list.stream();
Optional<E> optional = stream
.sorted()
.collect(Collectors.maxBy((o1, o2) ->
sorted ? o1.compareTo(o2) == 1 ? 0 : 1
: o1.compareTo(o2)));
return optional.isPresent() ? optional.get() : list.get(0) ;
ابتدا یک Stream برای List ام ایجاد کردم(نکته!! این استریم هیچ ربطی به IO ,NIO استریم ها تو جاوا نداره.!)
بعد با کلاس Optional ابتدا استریم رو با شی Comparable پیش فرض که در تعریف متد مبینید سورت کردم
وبعد با متد Collect از استریم یه خروجی لیست جدید میگیریم منتهی با استفاده از کلاس Collectors متد MaxBy لیست جدید را داده کاوی میکنم با یک عبارت لاندا که از کلاس Comparator آبجکتها رو کنترل میکنم
و در نهایت با متد isPersent چک میکنم که آیا لیست جدید تشکیل شده است یا خیر در ضورت نبود هم من اولین عضو لیست هم را پاس میدم
فقط تو استفاده از Stream باید توجه داشته باشید برخی از متدهاش پایانی یعنی void هستن مثل foreach و مثل همین collect برخی هم میانی با خروجی هستن مثل Filter
اگر هم بخوام خیلی ساده بگم یعنی بعد از هر عملیات میانی میتونیم از متد های دیگه استریم استفاده کنیم و با الطبع بعد از هر عملیات پایانی هم نمی تونیم چون الگوی ساخت کلاس استریم Builder هست پس هر عملیات میانی همون شی جاری استریم هستش..!
برای minimum هم از این استفاده کنید!!!
.collect(Collectors.minBy((o1, o2) ->
sorted ? o1.compareTo(o2) == -1 ? 0 : 1
: o1.compareTo(o2)));
حالا وقتی نبود من اینو مینوشتم...
@Override
public <C extends Comparable<? super C>> C max(List<? extends C> list,C keyCompare) {
Iterator<? extends C> iterator = list.iterator();
C result = keyCompare;
while (iterator.hasNext()) {
C t = iterator.next();
if (t.compareTo(result) > 0) {
result = t;
}
}
return result;
}
امیدوارم بدردتون بخوره
-
نقل قول: قابلیت های جدید جاوا ۸
اینم یه روش برای Sort کردن یه لیست پیوندی به روش پاس دادن نوع مرتب سازی به متد...
@Override
public <E extends Comparator<? super E>> List<E> sortCollection(List<E> source_Collection ,Comparator<? super E> c) {
Stream<E> stream = source_Collection.stream();
source_Collection =stream.sorted(c).collect(Collectors.toList());
return source_Collection;
}
اگه نبود من اینو مینوشتم...
/**
* sort the stack collection O(N^2) N = stack.size()
* @param stack source stack collection
* @param <T> generic type mus be implemented Comparable interface.
* @return sorted stack collection.
*/
private <T extends Object & Comparable<? super T>> Stack<T> sort(Stack<T> stack) {
Stack<T> tStack = new Stack<>();
//loop the stack source collection is fill.
while (!stack.isEmpty()) {
T tmp = stack.pop();//save the first element from source stack list.
//tStack.peek().compareTo(tmp) compare to first element source stack list.
while (!tStack.isEmpty() && tStack.peek().compareTo(tmp) > 0) {
//tStack.pop() first element returned and removed.
//stack.push() write the first element from other stack list into source stack list.
stack.push(tStack.pop());
}
// write to the source stack collection.
tStack.push(tmp);
}
return tStack;
}
به نظرتون کدوم بهینه تره؟؟؟
-
نقل قول: قابلیت های جدید جاوا ۸
روش های دیگر برای ساخت استریم
استریمی از مقادیر
Stream<String> stringStream = Stream.of("a","b","c");
استریمی از آرایه
String[] strings = new String[]{"Ali","Farhad","Reza"};
Stream<String> stringStream = Arrays.stream(strings);
استریمی از فایل
try(Stream<String> lines = Files.lines(Paths.get("data.txt"))){
long count = lines.count();
} catch (IOException e) {
e.printStackTrace();
}
در روش استریم فایل چون که استریم واسط Closeable پیاده سازی میکنه از دستور Try..Catch..WithResource استفاده کردم که تو جاوا 7 اومده
-
نقل قول: قابلیت های جدید جاوا ۸
در ضمن استریم هارو میتونیم کلا پارالل هم بنویسیم کسی علاقه ای داشت بگه توضیح بدم اگر مبینید نگفتم چون یکسری تکنیک داره استفاده بی مورد نه تنها مفید نیست بلکه زیان آور هم هست دوستان خواهش فقط نیایید بخونید یه نظرم ارسال کنید ببینیم چند چندیم !؟
البته با تشکر از دوست عزیزم vahid-p
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
نوشته شده توسط
farhad_shiri_ex
در ضمن استریم هارو میتونیم کلا پارالل هم بنویسیم کسی علاقه ای داشت بگه توضیح بدم اگر مبینید نگفتم چون یکسری تکنیک داره استفاده بی مورد نه تنها مفید نیست بلکه زیان آور هم هست دوستان خواهش فقط نیایید بخونید یه نظرم ارسال کنید ببینیم چند چندیم !؟
البته با تشکر از دوست عزیزم vahid-p
البته تو این تاپیک استثنا بهتره نظر داده نشه. اینجا قابلیت های جاوا 8 معرفی میشه واگر بخواد پرسش و پاسخ و نظر و ابهام مطرح بشه، خیلی بد میشه (هر چند معمولا کسی نظر نمیده :لبخند:)
فقط اگر ممکنه TRY...CATCH...FINALLY که گفتید میشه مختصر نوشت با Predicate رو یه توضیح بدید (به جز حالت Stream ها که ساده تر نوشته میشه). با تشکر
-
نقل قول: قابلیت های جدید جاوا
سلام
آیا امکان آموزش آنلاین هم دارین؟
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
فقط اگر ممکنه TRY...CATCH...FINALLY که گفتید میشه مختصر نوشت با Predicate رو یه توضیح بدید (به جز حالت Stream ها که ساده تر نوشته میشه). با تشکر
من درست متوجه منظورت نشدم اگر منظورت استفاده از Try ...Catch ...WithResource چشم.!
کلا وقتی از کلاسهایی رو که واسط Closeable رو پیاده سازی میکنن یک آبجکت جدید ایجاد کردیم بعد از اینکه دیگه لازمش ندارید یا دستی خودتون آبجکت رو Close میکنین یا تو متد Finalize دستور Close میذارید که GC آبجکت رو برای شما از بین ببره ولی بااستفاده از این TRY..Catch...Resorce خود همین بلاک در زمانی که دیگه نیازی به آبجکت ندارید و کارتون باهاش تموم شده به صورت اتوماتیک خودش متد close رو صدا میزنه در حقیقت بعد از به اتمام رسیدن بلوک Try کار بستن رو انجام میده چه خطایی باشه و چه نباشه.
اینهم یه نمونه دیگه که تو استفادده از استریم فایلهاست.
public static int attachedDatabase(Context ctx) throws Exception {
int req;
try (InputStream _upgraded_db = ctx.getAssets().open(DB_NAME)){
String _current_db = ctx.getDatabasePath(DB_NAME).getPath();
File _DataBaseFile_= new File(_current_db);
if (_DataBaseFile_.exists()) {
DataBaseService dbService = DataBaseService.newInstance(ctx);
dbService.autoCloseObserver.onClose(false);
dbService.fetchRawRecord("SELECT "+KEY_ID+" FROM "+TABLE_PROFILE,null,null);
if (sDbOldVersion < sDbNewVersion)
req = setupScript(ctx, sDbOldVersion, sDbNewVersion) ? 1 : -1;
else
req =2 ;
} else {
String _empty_db_ = _current_db.substring(1,_current_db.indexOf(DB_NAM E)) ;
File _MainPath_ = new File(_empty_db_);
//noinspection ResultOfMethodCallIgnored
_MainPath_.mkdirs();
req = copyDb(_upgraded_db, new FileOutputStream(_current_db)) ? 1 : -1;
}
} catch (Exception e) {
throw new Exception(e.getMessage());
}
return req;
}
فقط حتما باید مقداردهی و تعریف متغیری که می خواهید AutoClose باشه توی پرانتز همون دستور Try باشه وگرنه خطا میگیره
ودیگه اینکه میتونید چند دستور تعریف و مقداردهی رو باهم انجام بدید فقط بین اونها یه (;) بذارید.
موفق باشید
-
نقل قول: قابلیت های جدید جاوا ۸
نقل قول:
فقط اگر ممکنه TRY...CATCH...FINALLY که گفتید میشه مختصر نوشت با Predicate رو یه توضیح بدید
اگر منظورتون اینه که بتونیم Predicate رو جایگزین Try...Catch کنیم که باید بگم که کلا این اینترفیس کارش اینه که جلوی Null Pointer رو بگیره با متد هایی که داره حالا اگر از try catch برای Null Pointer Exception استفاده میکنید آره پیشنهاد منم اینه که از این اینترفیس استفاده کنید چون همونطور که می دونید بلوک try catch خطاهای منطقی رو تو زمان اجرا wrap میکنه که این برای دیباگ کردن برنامه کار و سخت میکنه.
Predicate<String> nonNull = Objects::nonNull;
Predicate<String> isEmpty = String::isEmpty;
private Object myTest(String myObject) {
if(nonNull.negate().and(isEmpty).test(myObject))
return "is null";
return myObject + "test";
/*-----------------------------------*/
try {
if(!myObject.isEmpty())
myObject = myObject + "test";
return myObject;
} catch (NullPointerException e) {
return "is null";
}
}
-
نقل قول: قابلیت های جدید جاوا ۸
فرض کنید که از لیست کارکنان یک مجموعه می خواهید 10 نفر از مردها را انتخاب کنید که حقوق شان کمتر از 1000 و براساس حقوق مرتب کنید و هم زمان در خروجی نمایش بدید فکر کنید اگر استریم نبود باید چند خط کد می نوشتید..!!
public class SampleStream {
public static void main(String[] args) {
List<Employee> employeeList = new ArrayList<>();
employeeList.add(new Employee("farhad",800, true));
employeeList.add(new Employee("ali",1500000, true));
employeeList.add(new Employee("morteza",600, true));
employeeList.add(new Employee("hasan",700, true));
employeeList.add(new Employee("goli",1800000, true));
Predicate<Employee> predicate = (employee) -> (employee.gender && employee.salary < 1000);
Comparator<Employee> comparator = Comparator.comparingInt(a -> a.salary);
Consumer<Employee> consumer = (employee) -> System.out.printf("%s ,%d \n",employee.name ,employee.salary);
employeeList
.stream()
.parallel()
.filter(predicate)
.sorted(comparator)
.limit(10)
.forEach(consumer);
}
private static class Employee {
private String name ;
private int salary ;
private boolean gender ;
Employee(String name, int salary, boolean gender) {
this.name = name;
this.salary = salary;
this.gender = gender;
}
}
}
-
نقل قول: قابلیت های جدید جاوا ۸
جستجوی یک رشته در یک آرایه با جاوا 8 و قبل از جاوا 8 ...
String[] strArray = { "test", "test2" };
// Java 8 string check
System.out.println(Stream.of(strArray).anyMatch(x -> x == "test2"));
// Java 8 integer check
int[] intArray = new int[]{0,1,2,3,4,5,6};
System.out.println(IntStream.of(intArray).anyMatch (x -> x == 4));
//Java Array contains value for old versions
String[] strArray = { "test", "test2" };
System.out.println(Arrays.asList(strArray).contain s("test2"));
-
نقل قول: قابلیت های جدید جاوا ۸
استفاده از کلاس مقایسه گر بدون استفاده از Try... Catch !!
قبل از جاوا 8 اگر می خواستید یک شی مقایشه گر بنویسید باید حتما زمان استفاده از شی اون از بابت Null بودن پارامترهاش ایزوله میکردین مثل کد زیر
Comparator<person> myC = new Comparator<person>() {
@Override
public int compare(person o1, person o2) {
return o1.name.compareTo(o2.name);
}
};
person p1 = new person();
p1.name = "ali";
person p2 = new person();
p2.name = "reza";
try{
System.out.println("Compare ->" + myC.compare(p1,p2));
}catch(NullPointerException e){
e.printStackTrace();
}
حالا در جاوا 8 می تونید اینطوری استفاده کنید با استفاده از متدهای nullsLast ویا nullsFirst جلوی Null Pointer Exception را بگیرید
Comparator<person> myC = Comparator.comparing(o -> o.name);
Comparator<MyCompare.person> myCNoNull = Comparator.nullsLast(myC);
System.out.println("Compare not null checked ->" + myCNoNull.compare(p1,p2));
System.out.println("Compare not null checked ->" + myCNoNull.compare(p1,null));
-
نقل قول: قابلیت های جدید جاوا ۸
Composing Function
برای مقایسه دو فیلد ویا چند فیلد از یک کلاس با استفاده از Function Interface به صورت زیر عمل کنید
public class MyCompare {
private static class person {
String name;
int salary ;
person(String name, int salary) {
this.name = name;
this.salary = salary;
}
String getName() {
return this.name;
}
int getSalary(){
return this.salary;
}
}
public static void main(String[] args) {
person p1 = new person("ali",1000);
person p2 = new person("ali",2000);
Comparator<person> byName = Comparator.comparing(person::getName);
Comparator<person> bySalary = Comparator.comparingInt(person::getSalary);
Comparator<person> byNameAndSalary = byName.thenComparing(bySalary);
System.out.println("compare name and salary ->" + byNameAndSalary.compare(p1,p2));
}
}
-
نقل قول: قابلیت های جدید جاوا ۸
Parallel Stream
برای موازی کردن پردازش ها در زمان استفاده از کلاس استریم باید توجه به Race Condition ها در ناحیه اشتراکی داشته باشید در مثال زیر سعی شده این مطلب به سادگی نمایش داده بشه!
کلاسی ایجاد شده است که به جای یک Consumer اینترفیس که در تکرار گر Foreach استریم استفاده شده که کار جمع کردن مقادیر را به عهده داره همونطور که مشاهده میکنید در مثال اول بدون هیچگونه همگام سازی با استفاده از parallel موازی سازی انجام شده که مطمئنا Race Condition رخ میده برای رفع این مشکل از ناحیه اشتراکی همگام سازی شده Synchronization جاوا استفاده نشده به علت مسائلی که داره Thread Yield با کاهش وحشتناک سرعت روبه رو خواهیم شد. به همین علت در مثال دوم از کتابخانه Atomic جاوا و کلاس LongAddr استفاده میکنیم تا این مشکل تداخل در دستیابی به داده اشتراکی را رفع کنیم.
private static class person {
String name;
int salary ;
person(String name, int salary) {
this.name = name;
this.salary = salary;
}
String getName() {
return this.name;
}
int getSalary(){
return this.salary;
}
}
static class SalarySum {
static int total ;
static void accept(person p) {
total += p.getSalary(); //race condition unpredictable wrong results!!
}
int getTotal() {
return total;
}
}
public static void main(String[] args) {
List<person> personList = new ArrayList<>();
personList.add(new person("a",1000));
personList.add(new person("b",2000));
personList.add(new person("c",3000));
SalarySum salarySum = new SalarySum();
personList.stream()
.parallel()
.forEach(SalarySum::accept);
int totalSalary = salarySum.getTotal();
}
اصلاح مشکل ...
private static class person {
String name;
int salary ;
person(String name, int salary) {
this.name = name;
this.salary = salary;
}
String getName() {
return this.name;
}
int getSalary(){
return this.salary;
}
}
static class SalarySum {
static LongAdder totalSync = new LongAdder();
static void acceptSync(person p) {
totalSync.add(p.getSalary());
}
long getTotalSync() {
return totalSync.longValue();
}
}
public static void main(String[] args) {
List<person> personList = new ArrayList<>();
personList.add(new person("a",1000));
personList.add(new person("b",2000));
personList.add(new person("c",3000));
SalarySum salarySum = new SalarySum();
personList.stream()
.parallel()
.forEach(SalarySum::acceptSync);
long totalSalary2 = salarySum.getTotalSync();
}