مرتبسازی با استفاده از عبارات لامبدا در جاوا 8

public class Human { private String name; private int age; // standard constructors, getters/setters, equals and hashcode }
2- مرتبسازی پایه بدون استفاده از لامبدا
new Comparator<Human>() { @Override public int compare(Human h1, Human h2) { return h1.getName().compareTo(h2.getName()); } }
این Comprator برای مرتبسازی لیست نمونههای Human به سادگی مورد استفاده قرار میگیرد:
@Test public void givenPreLambda_whenSortingEntitiesByName_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Collections.sort(humans, new Comparator<Human>() { @Override public int compare(Human h1, Human h2) { return h1.getName().compareTo(h2.getName()); } }); Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
3- مرتبسازی پایه با کمک لامبدا
با معرفی لامبداها، میتوانیم از ایجاد کلاس داخلی بینام صرف نظر کرده و با استفاده از semanticهای تابعی و ساده، به نتایج مشابهی دست یابیم:
(final Human h1, final Human h2) -> h1.getName().compareTo(h2.getName());
همچنین مانند قبل میتوانیم نتیجه را تست کنیم:
@Test public void whenSortingEntitiesByName_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); humans.sort( (Human h1, Human h2) -> h1.getName().compareTo(h2.getName())); assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
توجه داشته باشید که به جای API قدیمی Collections.sort، از API جدید مرتبسازی که به java.util.List در جاوا 8 اضافه شده استفاده میکنیم.
4- مرتبسازی پایه بدون تعریف نوع
میتوانیم عبارت مرتبسازی را با استفاده نکردن از تعریف نوع، باز هم سادهتر کنیم. کامپایلر خودش قادر است استنتاج نوع انجام دهد:
(h1, h2) -> h1.getName().compareTo(h2.getName())
و مجددا، میتوانیم نتیجه را تست کنیم:
@Test public void givenLambdaShortForm_whenSortingEntitiesByName_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName())); assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
5- مرتبسازی با استفاده از «ارجاع به متدهای استاتیک»
در قدم بعدی، با استفاده از عبارت لامبدا و ارجاع به یک متد استاتیک، قصد داریم عمل مرتبسازی را انجام دهیم.
ابتدا، متد compareByNameThenAge را با امضایی کاملا مشابه با متد compare در شی <Comparator<Human تعریف میکنیم:
public static int compareByNameThenAge(Human lhs, Human rhs) { if (lhs.name.equals(rhs.name)) { return lhs.age - rhs.age; } else { return lhs.name.compareTo(rhs.name); } }
حالا متد humans.sort را با این ارجاع فراخوانی میکنیم:
humans.sort(Human::compareByNameThenAge);
نتیجه نهایی، مرتبسازی یک مجموعه با استفاده از متد استاتیک به عنوان Comparator است.
@Test public void givenMethodDefinition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); humans.sort(Human::compareByNameThenAge); Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
6- مرتبسازی با استفاده از «ارجاع به متدهای شی»
حتی میتوانیم با استفاده از ارجاع به متد شی (instance method reference) و متد Comparator.comparing، از تعریف منطق مقایسه هم خودداری کنیم.
از ()getName برای ساخت عبارت لامبدا و مرتبسازی لیست بر اساس نام استفاده میکنیم:
@Test public void givenInstanceMethod_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Collections.sort( humans, Comparator.comparing(Human::getName)); assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
7- مرتبسازی وارونه
JDK 8 یک متد کمککننده (helper) برای وارونهسازی comparator معرفی کرده است. میتوانیم خیلی سریع با استفاده از آن، مرتبسازی وارونه را انجام دهیم:
@Test public void whenSortingEntitiesByNameReversed_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Comparator<Human> comparator = (h1, h2) -> h1.getName().compareTo(h2.getName()); humans.sort(comparator.reversed()); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); }
8- مرتبسازی بر اساس چند شرط مختلف
عبارتهای لامبدایی لزوما نباید خیلی ساده باشند و میتوانیم عبارات پیچیدهتر هم بنویسیم. برای مثال، مرتبسازی اشیا ابتدا بر اساس نام و سپس بر اساس سن:
@Test public void whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12) ); humans.sort((lhs, rhs) -> { if (lhs.getName().equals(rhs.getName())) { return lhs.getAge() - rhs.getAge(); } else { return lhs.getName().compareTo(rhs.getName()); } }); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); }
9- مرتبسازی بر اساس چند شرط مختلف – composition
همین منطق، یعنی ابتدا مرتبسازی بر اساس نام و سپس بر اساس سن، میتواند با کمک composition هم انجام شود.
پس از جاوا 8، میتوانیم برای ساخت منطقهای مقایسهای پیچیدهتر، چندین comparator را به هم زنجیر کنیم:
@Test public void givenComposition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12) ); humans.sort( Comparator.comparing(Human::getName).thenComparing(Human::getAge) ); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); }
10- مرتبسازی یک لیست با استفاده از ()Stream.sorted
همچنین، میتوانیم یک مجموعه را با استفاده از Stream.sorted() API مرتب کنیم.
میتوانیم استریم را بر اساس ترتیب طبیعی و یا ترتیبی حاصل از یک Comparator، مرتب کنیم. برای این منظور، دو نوع مختلف overloadشده از sorted() API داریم:
- ()sorted: آیتمهای استریم را با ترتیب طبیعی مرتب میکند. البته کلاس مربوط به اشیای داخل استریم، باید واسط Comparable را پیادهسازی کرده باشد.
- (sorted(Comparator<? superT> comparator: آیتمها را بر اساس یک نمونه comparator مرتب میکند.
یک مثال از نحوه استفاده از متد ()sorted با ترتیب طبیعی ببینیم:
@Test public final void givenStreamNaturalOrdering_whenSortingEntitiesByName_thenCorrectlySorted() { List<String> letters = Lists.newArrayList("B", "A", "C"); List<String> sortedLetters = letters.stream().sorted().collect(Collectors.toList()); assertThat(sortedLetters.get(0), equalTo("A")); }
حالا، ببینیم که چطور میشود از یک Comparator سفارشی در sorted() API استفاده کرد:
@Test public final void givenStreamCustomOrdering_whenSortingEntitiesByName_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); Comparator<Human> nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName()); List<Human> sortedHumans = humans.stream().sorted(nameComparator).collect(Collectors.toList()); assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12))); }
اگر از متد ()Comparator.comparing استفاده کنیم، میتوانیم مثال بالا را سادهتر هم بکنیم:
@Test public final void givenStreamComparatorOrdering_whenSortingEntitiesByName_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); List<Human> sortedHumans = humans.stream() .sorted(Comparator.comparing(Human::getName)) .collect(Collectors.toList()); assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12))); }
11- مرتبسازی یک لیست به صورت وارونه با استفاده از ()Stream.sorted
همچنین میتوانیم از ()Stream.sorted برای مرتبسازی یک مجموعه به صورت وارونه استفاده کنیم.
ابتدا، بیایید مثالی از نحوه ترکیب متد ()sorted با ()Comparator.reverse برای مرتبسازی وارونه یک لیست بر اساس ترتیب طبیعی ببینیم:
@Test public final void givenStreamNaturalOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() { List<String> letters = Lists.newArrayList("B", "A", "C"); List<String> reverseSortedLetters = letters.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); assertThat(reverseSortedLetters.get(0), equalTo("C")); }
حالا، ببینیم که چطور میتوانیم از متد ()sorted و یک Comparator سفارشی استفاده کنیم:
@Test public final void givenStreamCustomOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); Comparator<Human> reverseNameComparator = (h1, h2) -> h2.getName().compareTo(h1.getName()); List<Human> reverseSortedHumans = humans.stream().sorted(reverseNameComparator) .collect(Collectors.toList()); assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10))); }
توجه کنید که compareTo فراخوانی شده است و همین است که کار وارونه کردن مرتبسازی را انجام میدهد.
نهایتا، بیایید مثال بالا را با استفاده از متد ()Comparator.comparing سادهسازی کنیم:
@Test public final void givenStreamComparatorOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); List<Human> reverseSortedHumans = humans.stream() .sorted(Comparator.comparing(Human::getName, Comparator.reverseOrder())) .collect(Collectors.toList()); assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10))); }
12- جمعبندی
در این مقاله، بدون درگیر شدن در پیچیدگیهای سینتکسی، روشهای مختلفی که یک لیست با استفاده از عبارات لامبدای جاوا 8 میتواند مرتب شود، با مثالهای مختلف توضیح داده شد.
.
.
.
آدرس کانال تلگرام: JavaCupIR@
آدرس اکانت توییتر: JavaCupIR@
آدرس صفحه اینستاگرام: javacup.ir
آدرس گروه لینکدین: Iranian Java Developers
سلام
بسیار عالی و مفید
تشکر
موفق باشید
سلام من میخواستم آموزش php سون لرن رو بخرم میخواستم بدونم اون بهتره یا جاوا سایت شما خیلی عالیه من تازه آشنا شدم کمکم کنید
سلام
بهتر و بدتری در این زمینه وجود نداره.
شما باید با توجه به کاری که قرار هست یا دوست دارید انجام بدید، تصمیم بگیرید که جاوا یاد بگیرید یا php