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

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

* জাভা কালেকশান ফ্রেমওয়ার ভুমিকা
* কালেকশান ইন্টারফেইস
* লিস্ট
* সর্টেট লিস্ট
* ম্যাপ
* সর্টেট ম্যাপ
* নেভিগেবল ম্যাপ
* সেট
* সর্টেট সেট
* নেভিগেবল সেট
* 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;
            }

        });
```

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://java.howtocode.dev/11.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
