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

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

কালেকশান ফ্রেমওয়ার্ক

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

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

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

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

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

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

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

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

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

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

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 ডিক্লেয়ার করার নানা ধাপঃ

ধাপ ১ঃ

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();
    }
}

ধাপ ২ঃ

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();
    }
}

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

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)

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)

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

পদ্ধতি ১ঃ

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

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

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

পদ্ধতি ২ঃ

        for(int x: list){

            System.out.println(x);
        }

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

পদ্ধতি ৩ঃ

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

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

পদ্ধতি ৪ঃ

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

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

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

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

list.set(2, Integer.MAX_VALUE);

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

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

পদ্ধতি ১ঃ

list.remove(2);

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

পদ্ধতি ২ঃ

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)

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

পদ্ধতি ১ঃ

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 অবজেক্ট । যেটার মাধ্যমে আমরা বলে দিব যে আসলে সর্টটি কোন অর্ডারে হবে বা কোন এলিমেন্টের সাপেক্ষে হবে । কোডটিকে সেক্ষেত্রে আমরা এভাবে লিখতে পারতাম,

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 এর অবজেক্ট ক্রিয়েট না করেও কাজটি করতে পারতাম ইনপ্লেসে । সেক্ষেত্রে এরকম হতে পারত,

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

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

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

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

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

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);
        });
    }
}

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

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

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

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);
        });
    }
}

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

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 মেথড ব্যাবহার করেও সর্ট করতে পারতেন । সেটা করার জন্য খুব বেশি কিছুই করতে হতনা । সেটি অলরেডি আপনারা জানেন কিভাবে সেটি করা যায় ।

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

        });

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

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