# পাঠ ১১: জাভা কালেকশান ফ্রেমওয়ার্ক

\# পাঠ ১১: জাভা কালেকশান ফ্রেমওয়ার্ক

* জাভা কালেকশান ফ্রেমওয়ার ভুমিকা
* কালেকশান ইন্টারফেইস
* লিস্ট
* সর্টেট লিস্ট
* ম্যাপ
* সর্টেট ম্যাপ
* নেভিগেবল ম্যাপ
* সেট
* সর্টেট সেট
* নেভিগেবল সেট
* Queue এবং Deque
* স্ট্যাক
* hashCode() এবং equals()
* সারসংক্ষেপ

**কালেকশান ফ্রেমওয়ার্ক**

কালেকশন ফ্রেমওয়ার্ক জাভার টপ লেভের একটি এপিআই কনসেপ্ট । কালেকশান ফ্রেমওয়ার্ক কিছু হাইলি অপটিমাইজড ডাটা স্ট্রাকচার যার মাধ্যমে বিভিন্ন ডাটা মেমোরিতে স্টোর করতে পারি এবং প্রয়োজন মত ব্যাবহার করতে পারি । মনে করুন অ্যারে নিয়ে কাজ করছেন । কোন একটি সময়ে মনে হল আপনার অ্যারের সাইজ যথেষ্ঠ নয় আপনার কাজের জন্য তখন কি করবেন ? মনে করুন আপনি লিংকড লিস্ট নিয়ে কাজ করছেন কোন একটা সময়ে একটা এলিমেন্ট সার্চ করার প্রয়োজন হলো , সার্চ করলেন । দেখা গেল অনেক্ষন পর রেজাল্ট জানালো যে সেই এলিমেন্ট ওই লিস্টেই নাই । এরকম নানা রকম সমস্যা এবং তার সমাধান নিয়ে যে সব ডাটা স্ট্রাকচার একত্রিত করা হয়েছে সেগুলাকেই একত্রে বলা হয় কালেকশান । কালেকশান মানে হল সমষ্টি । এটি এমন কিছু ডাটা স্ট্রাকচারের সমষ্টি যেগুলার প্রতিটিই বিভিন্ন ডাটাকে সমষ্টিত করে রাখে । হ্যা অ্যারেকেও লো লেভেল এক প্রকার কালেকশান বলা যেতে পারে তবে মডার্ন কালেকশন ফ্রেমওয়ার্কের মাঝে এটিকে ধরা হয়না ।

**কালেকশান ইন্টারফেস (Collection Interface)**

ইন্টারফেস কি সেটি আপনারা খুব ভালোভাবেই জানেন । যদি না যেনে থাকেন তবে চ্যাপটার ৫.১ পড়ে আসুন । কালেকশান একটি ইন্টারফেস । যেই ইন্টারফেসের মধ্য বলে দেওয়া হয়েছে কোন একটি ক্লাসকে কালেকশান ফ্রেমওয়ার্কের অন্তর্গত হতে গেলে কি কি বৈশিষ্ট থাকতেই হবে । কালেশনগুলা সাধারনত `java.util` প্যকেজের অন্তর্গত ।

সবার আগে আমাদের জানা প্রয়োজন কেনই বা আমরা কালেকশনস নিয়ে কাজ করবো ? এটি না নিয়েও তো কাজ করা যেতো । তাহলে কালেকশন কেন !

ওয়েল , আপনাদের কিছুটা উত্তর আমি আগেই দিয়ে দিয়েছি ।

১)অ্যারে নিয়ে কাজ করার সময় আপনি ফিক্সড লেন্থের বাইরে কাজ করতে পারতেন না । অ্যারের বাউন্ডারি ফিক্সড এবং এটি বাড়ানো বা কমানোর কোন সুযোগ নেই রানটাইমে । কালেকশন এই সমস্যার সমাধান করেছে । এটির সাইজ আপনার প্রয়োজন মত বাড়াতে এবং কমাতে পারবেন ।

২)লিংক লিস্ট নিয়ে কাজ করার সময় আপনি ইনডেক্সের সুবিধা পাবেন না । এটা একটা বড় সমস্যার কারন, কালেকশনে আপনি ইন্ডেক্স সুবিধা পাবেন ।

৩)কেবল প্রিমিটিভ নয়, সকল প্রকার অবজেক্ট এমনি একটি কালেকশনের মাঝে আরেকটি কালেকশন নিয়ে কাজ করার মত ফ্লেক্সিবিলিটি পাবেন ।

এছাড়া আরো বহুত সুবিধা আছে যেগুলা কাজ করতে করতে বুঝে যাবেন ।

নিচে কালেকশান ফ্যামিলি ট্রি দেখানোর চেষ্টা করা হল ।

```java
Collection<Interface>
    Set<Interface>
        HashSet
        LinkedHashSet
        SortedSet<Interface>
            TreeSet
    List<Interface>
        ArrayList
        Vector
        LinkedList
    Queue<Interface>
        LinkedList
        PriorityQueue

Object
    Arrays
    Collections

Map<Interface>
    HashTable
    LinkedHashMap
    HashMap
    SortedMap<Interface>
        TreeMap
```

**লিস্ট ( List )**

লিস্ট `List` একটি ইন্টারফেস যেটি সরাসরি `Collection` ইন্টারফেসকে এক্সটেন্ড করেছে । এটি যেহেতু একটি ইন্টারফেস ( `interface` ) তাই আমরা সরাসরি এটার কোন অবজেক্ট বা ইন্সট্যান্স ক্রিয়েট করতে পারবো না । এজন্য অবশ্য আমাদের চিন্তার খুব বেশি কারন নেই । `List` ইন্টারফেসকে ইমপ্লিমেন্ট করেছে `ArrayList` , `Vector` এবং `LinkedList` ক্লাস । আমরা খুব সহজে এগুলার মাধ্যমে `List` এর অবজেক্ট তৈরি করতে পারি । `List` হল আনসর্টেড অবজেক্ট কনটেইনার যেটি ডাটা ডুপ্লিকেসি সাপোর্ট করে । মানে একই ডাটা একাধিকবার থাকতে পারে লিস্টের মাঝে ।

`List` ডিক্লেয়ার করার নানা ধাপঃ

ধাপ ১ঃ

```java
import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
import java.util.Vector;
public class Main {
    public static void main(String[] args) {
        List list, list2, list3;
        list = new ArrayList();
        list2 = new LinkedList();
        list3 = new Vector();
    }
}
```

ধাপ ২ঃ

```java
import java.util.ArrayList;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        List list1 = new ArrayList();
        ArrayList list2 = new ArrayList();
    }
}
```

এমনকি কেউ চাইলে কালেকশনের অবজেক্ট নিয়েও কাজ করতে পারেন সেক্ষেত্রে যেটি করতে হবে ।

```java
import java.util.ArrayList;
import java.util.Collection;
public class Main {
    public static void main(String[] args) {
        Collection c = new ArrayList();
    }
}
```

ওকে অনেক হয়েছে । এবার কাজের কথায় আসা যাক । `List` নিয়ে কিভাবে কাজ করা যায় সেটাইতো জানা হলোনা এখনো ! ওকে আর বেশি বক বক করে আপনাদের ধৈর্য্যের পরীক্ষা নিবনা । প্রথমে আমরা দেখবো কিভাবে একটি লিস্টে ডাটা অ্যাড বা অ্যাসাইন করতে হয় ।

**লিস্টে ডাটা ইনসার্ট(Insert into List)**

```java
import java.util.ArrayList;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(7);
        list.add(5);
        list.add(13);
        list.add(17);
        list.add(3);
    }
}
```

উপরোক্ত কোডে `<Integer>` দিয়ে বোঝানো হয়েছে এই লিস্টটি কেবল ইন্টিজার টাইপ ডাটার জন্য কাজ করবে । এটিকে জেনেরিক বলা হয় । চ্যাপটার ৮ এ আপনাদের এ বিষয়ে জানা কথা । তারপর `ArrayList` এর কনস্ট্রাকটর দিয়ে `list` অবজেক্টকে ইন্সট্যানশিয়েট করা হয়েছে । `add` মেথড এই লিস্টে একটি একটি করে ডাটা অ্যাড করে এবং একটি বুলিয়ান ভ্যালু রিটার্ন করে । যদি কোন কারনে কোন ডাটা অ্যাড করতে ব্যার্থ হয় তবে `false` ভ্যালু রিটার্ন করে ।

`add(int index, E element)` মেথডটি যেকোন একটি এলিমেন্ট লিস্টের নির্দিষ্ট ইনডেক্সে ইনসার্ট করে । `addAll(Collection<? Extends E> c)` মেথডটি ইনপুট প্যারামিটার হিসাবে অন্য কোন একটি লিস্ট বা কালেকশন নিয়ে তার প্রতিটি এলিমেন্ট একটু একটি করে এই লিস্টে ইনসার্ট করে দেয় । `addAll(int index, Collection<? Extends E> c)` মেথডটি ঠিক আগের মতই কাজ করে । নির্দিষ্ট ইনডেক্স থেকে অন্য একটি কালেকশনকে ইনজেক্ট করতে থাকে নতুন লিস্টের মাঝে ।

**লিস্ট থেকে ডাটা রিড করা(Read from List)**

উপরের কোড সেগমেন্টটি মনে করলাম আছে । আমরা কেবল ডাটা রিড করার জন্য কোডটি লিখবো । আমরা বেশ কয়েকভাবে দেখবো যে কিভাবে একটি লিস্ট থেকে ডাটা রিড করা যায় এবং এর মাধ্যমে আরো কিছু মেথড সম্পর্কে জেনে নিব ।

পদ্ধতি ১ঃ

```java
        for(int i=0; i<list.size(); i++){

            System.out.println(list.get(i));
        }
```

এটি একেবারে চীরাচরিত পদ্ধতি হলেও বেশ কার্যকর । এখানে অ্যারের মত ইন্ডেক্স নিয়ে খেলা করার সুযোগ আছে । `size` মেথডটি একটি ইন্টিজার নাম্বার রিটার্ন করে যেটি নির্দেশ করে এই লিস্টে মোট কতগুলা এলিমেন্ট আছে । মানে এই লিস্টের সাইজ কত । `get` মেথডটি একটি ইন্টিজার নাম্বার ইনপুট হিসাবে নেয় এবং সেই ইন্ডেক্সের এলিমেন্টটি রিটার্ন করে । এমন কোন ইনডেক্স যদি ইনপুট হিসাবে দেওয়া হয় যেটি এই লিস্টের সাইজের মাঝে পড়েনা তাহলে `java.lang.IndexOutOfBoundsException` এক্সেপশন থ্রো করবে ।

পদ্ধতি ২ঃ

```java
        for(int x: list){

            System.out.println(x);
        }
```

এটি একেবারে চীরাচরিত পদ্ধতি থেকে একটু আধুনিক । এনহ্যান্স ফর লুপ । এই পদ্ধতিতে এনহ্যান্স ফর লুপ লিস্ট থেকে একটি একটি এলিমেন্ট প্রতি এলিমেন্টে পিক করে `x` ভ্যারিয়েবলের মাঝে রেফার করছে এবং সেটিই আমাদের সামনে প্রদর্শিত হচ্ছে ।

পদ্ধতি ৩ঃ

```java
        Iterator it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
```

এটি আরো একটু মডারেট পদ্ধতি । এই পদ্ধতিতে প্রথমেই `Iterator` ইন্টারফেসের একটি ইন্সট্যান্স ক্রিয়েট করা হচ্ছে লিস্টের `iterator` মেথডটি কল করে । এই মেথডটি একটি ইটারেটর অবজেক্ট রিটার্ন করে যেটি এই লিস্টে টপ টু বটম ইটারেট করতে পারে । ইটারেটরের `hasNext` মেথডটি একটি বুলিয়ান ভ্যালু রিটার্ন করে । প্রতি ইটারেশনের পর সে বলে দেয় এর পর আর কোন এলিমেন্ট অবশিষ্ট আছে কি না । ইটারেটরের `next` মেথডটি প্রতিবার নতুন একটি এলিমেন্ট প্রভাইড করে এবং এটির কাউন্টার পয়েন্টার তার পরের ইনডেক্সে শিফ্ট করে । যাতে করে পরেরবার নতুন একটি এলিমেন্ট রিটার্ন করতে পারে ।

পদ্ধতি ৪ঃ

```java
        list.forEach((x) -> {
            System.out.println(x);
        });
```

হাল আমলের আলোচিত পদ্ধতি । এটিকে বলা হয় ফাংশনাল অপারেশন । জেডিকে ৮ এ এটিকে পরিচিত করানো হয়েছে । অনেকটা ফাংশনাল প্রাগ্রামিং এর মত করেই ডিজাইন করা করা । `forEach` মেথডটি একটি একটি করে এলিমেন্ট ট্রাভার্স করে যায় এবং তাকে যে কাজ করতে বলা হয় ঠিক সেই কাজটিই করে বসে থাকে । :D দারুন মজার এই ফাংশনার অপারেশন ।

**লিস্টের ভ্যালু রিপ্লেস করা**

কোন একটি লিস্ট থেকে খুব সহজেই একটি ভ্যালু রিপ্লেস করে দেওয়া যায় । `set(int index, E element)` মেথডটি ২ টি ইনপুর প্যারামিটার নেয় । প্রথমে যে ইনডেক্সের ভ্যালু রিপ্লেস করতে হবে সেটি এবং তার পরে যে অবজেক্ট দিয়ে সেই স্থান পূরন করতে হবে সেটি।

```java
list.set(2, Integer.MAX_VALUE);
```

**লিস্ট থেকে ডিলিট করা**

খুব প্রচলিত ২ উপায়ে লিস্ট থেকে কোন একটি এলিমেন্ট ডিলিট বা রিমুভ করে দেওয়া যায় । একটি হল কোন একদি এলিমেন্ট বা অবজেক্ট কোন ইনডেক্সে আছে সেটা জানা এবং সেই ইনডেক্সকে রিমুভ করে দেওয়া । অথবা যে অবযেক্টটি রিমুভ করতে চাওয়া হচ্ছে সেই অবযেক্টটি দিয়ে বলা সেটি ডিলিট করতে । চলুন দেখি সেটি কিভাবে করা যায়ঃ

পদ্ধতি ১ঃ

```java
list.remove(2);
```

এই পদ্ধতি আপনি প্রিমিটিভ ইন্টিজার নাম্বার নাম্বার ইনপুট প্যারামিটার হিসাবে পাস করছেন । অর্থাৎ `remove` মেথডটি এটিকে ইনডেক্স হিসাবে বিবেচনা করবে । যদি 2 নাম্বার ইনডেক্সে অন্য কোন নাম্বার থাকে এবং ২ লিস্টে উপস্থিত থাকে তার পরেও সে ২ নাম্বার ইনডেক্সের ভ্যালুটিকে রিমুভ করবে এবং ওই ইনডেক্সের ভ্যালুটি রিটার্ন করবে ।

পদ্ধতি ২ঃ

```java
list.remove(new Integer(13));
```

এই পদ্ধতিতে আপনার লিস্টটি যে টাইপের অবজেক্ট কনটেইন করছে সেই টাইপের একটি অবজেক্ট দিলে সেটিকে ডিলিট করার চেষ্টা করবে । যদি উক্ত অবজেক্ট উপস্থিত থাকে ডিলিট করবে এবং `true` ভ্যালু রিটার্ন করবে অন্যথায় `false` রিটার্ন করবে ।

**লিস্ট সম্পর্কিত কিছু মেথড(Some methods of List)**

`clear` মেথডটি উক্ত লিস্ট থেকে সব এলিমেন্ট রিমুভ করে দেয় । `contains` মেথডটি একটি অবজেক্ট ইনপুট হিসাবে নেয় এবং চেক করে যে উক্ত অবজেক্টরি লিস্টে প্রেজেন্ট কি না । ‍`indexOf` মেথসটি একটি অবজেক্ট ইনপুট হিসাবে নেয় এবং যদি সেই অবজেক্টটি ওই লিস্টে প্রেজেন্ট থাকে তবে তার ইনডেক্স রিটার্ন করে । অন্যথায় -১ রিটার্ন করে । `sort` নামক একটি মেথড আছে যেটি ইনপুট প্যারামিটার হিসাবে কম্পারেটর অবজেক্ট নিয়ে লিস্টটি সেই অনুযায়ী সর্ট করে ।

এরকম আরো বেশ কিছু মেথড এবং তাদের বিস্তর ব্যাখ্যা ওরাকলের অফিসিয়াল ডকুমেন্টেশন সাইটে পাওয়া যাবে । আগ্রহীরা সেখান থেকে দেখে নিতে পারেন । লিংকঃ <http://docs.oracle.com/javase/8/docs/api/java/util/List.html>

**লিস্ট সর্ট করা(Sort a List)**

কোন একটি লিস্টকে সর্ট করার চেয়ে সহজ বিষয় আর কিছু হতেই পারেনা । তবে সমস্যা হল একটি লিস্টকে সর্ট করার নানাবিধ উপায় থাকায় আপনি কনফিউজ হয়ে যেতে পারেন যে আসলে কক্ষন কোন পদ্ধতিতে সর্ট করবেন । আমি নিজেও মাঝে মাঝে কনফিউজ হয়ে যাই । যাইহোক আমরা লিস্ট সর্টিং এর একেবারে বেসিক থেকে ধীরে ধীরে সামনের দিকে এগিয়ে যাব । বলে রাখা ভালো আমরা এখানে বেসিক্যালি ২ প্রকারের সর্টিং টেকনিক দেখবো এবং তাদের আবার ২ প্রকার সাব সর্টিং টেকনিক দেখবো । আগ্রহীরা আরো কিছুটা ঘাটাঘাটি করলে আরো অনেক কিছুই জানতে পারবে ।

পদ্ধতি ১ঃ

```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();
        list.add(7);
        list.add(5);
        list.add(13);
        list.add(17);
        list.add(3);

        Collections.sort(list);

        list.forEach((x) -> {
            System.out.println(x);
        });
    }
}
```

এখানে আমরা `Collections` ক্লাসের একটি মেথড `sort` যেটি ইনপুট প্যারামিটার হিসাবে একটি লিস্ট অবজেক্ট নেয় এবং সেটিকে ইনপ্লেস সর্ট করে দেয় । অর্থাৎ এই মেথডের রিটার্ন টাইপ ভয়েড । এবং এটি অ্যাসেন্ডিং ( ছোট থেকে ক্রমান্বয়ে বড় ) অর্ডারে সর্ট করে ।

আমরা যদি ডিসেন্ডিং অর্ডারে সর্ট করতে চাই তবে আমাদের আরেকটু কাজ বেশি করতে হবে । আর সেটি হল `sort` নামক মেথডে আরেকটি প্যারামিটার পাস করতে হবে যেটি আসলে একটি `Comparator` অবজেক্ট । যেটার মাধ্যমে আমরা বলে দিব যে আসলে সর্টটি কোন অর্ডারে হবে বা কোন এলিমেন্টের সাপেক্ষে হবে । কোডটিকে সেক্ষেত্রে আমরা এভাবে লিখতে পারতাম,

```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();
        list.add(7);
        list.add(5);
        list.add(13);
        list.add(17);
        list.add(3);

        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer t1, Integer t2) {
                return t2-t1;
            }
        };

        Collections.sort(list, comparator);

        list.forEach((x) -> {
            System.out.println(x);
        });
    }
}
```

উল্লেখ্য এখানে `Comparator` একটি ইন্টারফেস এবং এবং `compare` একটি `abstract` মেথড তাই আমাদের এটিকে ইমপ্লিমেন্ট করতে হয়েছে । ‍`compare` মেথডটি একটি ইন্টিজার নাম্বার রিটার্ন করে । দুটি অ্যাট্রিবিউটের মাঝে কম্পেয়ার করে পজেটিভ, নেগেটিভ বা শুন্য রিটার্ন করে । শুন্য রিটার্ন করা মানে দুটি সমান । পজেটিভ রিটার্ন করা মানে প্রথমটি বড় আর অন্যথায় ছোট । আমরা আলাদা ভাবে `Comparator` এর অবজেক্ট ক্রিয়েট না করেও কাজটি করতে পারতাম ইনপ্লেসে । সেক্ষেত্রে এরকম হতে পারত,

```java
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer t, Integer t1) {
                return t1-t;
            }
        });
```

বর্তমান সময় যেহেতু ল্যামডা এক্সপ্রেশনের যুগ চলছে তাই এটিকে আরো সহজে এবং খুব সংক্ষেপে এভাবেও লেখা যেত,

```java
        Collections.sort(list, (Integer t1, Integer t2) -> t2-t1);
```

কাজ বেসিক্যালি সব একই ভাবে করছে ।

এতক্ষন আমরা দেখলাম প্রিমিটিভ টাইপের ডাটার একটি লিস্ট সর্ট করা । এমনতো হতেই পারে যে আপনার কাছে একটি কাষ্ট টাইপের অবজেক্ট কনটেইন করে এমন একটি লিস্ট সর্ট করতে হবে ওই অবজেক্টের নির্দিষ্ট কোন এক বা একাধিক প্রপার্টির সাপেক্ষে । সেক্ষেত্রে করনীয় কি সেটা এবার চলুন দেখে ফেলি ।

```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Employee {

    int id;
    String name;
    int age;
    int salary;

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
}

public class Main {

    public static void main(String[] args) {

        List<Employee> list = new ArrayList<>();
        list.add(new Employee(1, "Abul", 27, 35000));
        list.add(new Employee(2, "Babul", 25, 37000));
        list.add(new Employee(3, "Kabul", 29, 30000));
        list.add(new Employee(4, "Mofiz", 24, 36000));
        list.add(new Employee(5, "Hafiz", 28, 34000));

        Collections.sort(list, new Comparator<Employee>(){
            @Override
            public int compare(Employee t, Employee t1) {
                return t.age - t1.age;
            }
        });

        list.forEach((x) -> {
            System.out.println(x.salary);
        });
    }
}
```

ঠিক আগের মতই কাজ করতে পারবেন । তবে এখানে অবজেক্ট নিয়ে কাজ করতে হবে । এবং অবজেক্টের কোন ফিল্ডের রেসপেক্টে সর্ট করতে চাচ্ছেন সেটাও ডিফাইন করে দিতে হবে । অ্যাসেন্ডিং বা ডিসেন্ডিং যেকোন ভাবেই সর্ট করতে পারবে । এমনকি একাধিক ফিল্ডের রেসপেক্টে যদি সর্ট করতে চান সেটাও করতে পারবে । আপনারা চাইলে ল্যামডা এক্সপ্রেশন ব্যাবহার করতে পারতেন সেক্ষেত্রে এরকম হতো কোডটি,

```java
        Collections.sort(list, (Employee t, Employee t1) -> t1.age – t.age);//descending order
```

এবার আমরা একটু ভিন্ন একটা পদ্ধতি দেখবো । যদি এমন হয় যে আমাদের এই ক্লাসটি প্রায়ই সর্ট করতে হয় এবং নির্দিষ্ট একটা অর্ডারে সর্ট করতে হয় , সেক্ষেত্রে আমরা একটা বিশেষ কাজ করতে পারি । আমরা `Comparable` ইন্টারফেসটি ইমপ্লিমেন্ট করতে পারি । `Comparable` ইন্টারফেসের মাঝে `compareTo` মেথডটি অভাররাইড করলেই কাজ শেষ । অ্যাসেন্ডিং বা ডিসেন্ডিং আগের মতই । তবে চলুন দেখি কিভাবে সেটি করা যায় সেটি দেখে ফেলি ।

```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Employee implements Comparable<Employee> {

    int id;
    String name;
    int age;
    int salary;

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee t) {
        return this.age - t.age;
    }
}

public class Main {

    public static void main(String[] args) {

        List<Employee> list = new ArrayList<>();
        list.add(new Employee(1, "Abul", 27, 35000));
        list.add(new Employee(2, "Babul", 25, 37000));
        list.add(new Employee(3, "Kabul", 29, 30000));
        list.add(new Employee(4, "Mofiz", 24, 36000));
        list.add(new Employee(5, "Hafiz", 28, 34000));

        Collections.sort(list);

        list.forEach((x) -> {
            System.out.println(x.id + ", " + x.name + ", " + x.age + ", " + x.salary);
        });
    }
}
```

এভাবে খুব সহজেই আমরা একটি অবজেক্টের লিস্ট সর্ট করতে পারি । তবে একটি বিষয় লক্ষ করার মত বিষয় হচ্ছে যে আপনাদের যে ২ প্রকারের সর্ট দেখানো হয়েছে অবজেক্টের লিস্টের ক্ষেত্রে এই দুই প্রকার কিন্তু একত্রেও ব্যাবহার করতে পারবেন । তবে সেক্ষেত্রে প্রায়োরিটি পাবে ক্লোজার ফাংশন । চলুন দেখি বিষয়টা কি একটু দেখে নেই ।

```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Employee implements Comparable<Employee> {

    int id;
    String name;
    int age;
    int salary;

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee t) {
        return this.age - t.age;
    }
}

public class Main {

    public static void main(String[] args) {

        List<Employee> list = new ArrayList<>();
        list.add(new Employee(1, "Abul", 27, 35000));
        list.add(new Employee(2, "Babul", 25, 37000));
        list.add(new Employee(3, "Kabul", 29, 30000));
        list.add(new Employee(4, "Mofiz", 24, 36000));
        list.add(new Employee(5, "Hafiz", 28, 34000));

        Collections.sort(list, ((Employee e1, Employee e2) -> (e2.salary + e1.salary)));

        list.forEach((x) -> {
            System.out.println(x.id + ", " + x.name + ", " + x.age + ", " + x.salary);
        });
    }
}
```

এখানে যদিও `Employee` ক্লাস `Comparable` ইন্টারফেস ইমপ্লিমেন্ট করেছে এবং `compareTo` মেথডে বলে দেওয়া হয়েছে `age` এর অ্যাসেন্ডিং অর্ডারে সর্ট করতে হবে কিন্তু এটি সর্ট করবে `salary` এর ডিসেন্ডিং অর্ডারে । কেন সেটা করছে সেটা নিশ্চয় বুঝতে পেরেছেন ।

আপনারা চাইলে কিন্তু `List` এর অন্তর্গত `sort` মেথড ব্যাবহার করেও সর্ট করতে পারতেন । সেটা করার জন্য খুব বেশি কিছুই করতে হতনা । সেটি অলরেডি আপনারা জানেন কিভাবে সেটি করা যায় ।

```java
        list.sort(new Comparator<Employee>(){
            @Override
            public int compare(Employee t, Employee t1) {
                return t1.age - t.age;
            }

        });
```

বেসিক্যালি এভাবে খুব সহজেই একটি লিস্ট সর্ট করা যায় । আপনারা আরো বেশি আগ্রহী হলে ওরাকলের ডকুমেন্টেশন পড়তে পারেন । আরো বেশি পরিষ্কার হবে ধারনা ।

## –-------চলবে--------
