21. జావా కలెక్షన్స్ ఫ్రేమ్‌వర్క్ — List, ArrayList & LinkedList (Collections Mastery)

☕ Java (Java 21+ LTS) 🟢 Lesson 21 of 25 📂 Part 05: Collections & Capstone (Page 1 of 5) ⏱️ 26 min read
📌 Covered in this lesson: Collections Framework ఆర్కిటెక్చర్ · List ఇంటర్‌ఫేస్ · ArrayList (డైనమిక్ గ్రోత్, O(1) లుకప్) vs LinkedList (డబుల్ లింక్డ్ లిస్ట్, O(1) ఇన్సర్షన్) · ఇటరేటర్లు (Iterator, ListIterator)

సాఫ్ట్‌వేర్ అభివృద్ధిలో నిజమైన శక్తి డాటా స్ట్రక్చర్ల సమర్థవంతమైన నిర్వహణలోనే ఉంది. మనం 11వ అధ్యాయంలో నేర్చుకున్న సాధారణ జావా ఎరేలు అత్యంత వేగవంతమైనవి అయినప్పటికీ, వాటికి ఒక తీరని పరిమితి ఉంది — అదే స్థిర పరిమాణం (Fixed Size). రన్‌టైమ్‌లో యూజర్లు ఎన్ని వస్తువులు జోడిస్తారో ముందుగా తెలియనప్పుడు, ఎరేలు సరిపోవు. ఈ సమస్యను శాశ్వతంగా పరిష్కరించడానికి Java 1.2 లో ఆవిర్భవించిన మహోన్నత ఆర్కిటెక్చరే Java Collections Framework (JCF). అందులో డెవలపర్లు నిత్యం వాడే ప్రధాన భాగం List ఇంటర్‌ఫేస్. నిరంతరాయ మెమరీతో డైనమిక్‌గా 1.5 రెట్లు విస్తరించే ArrayList ఎలా పనిచేస్తుంది? పాయింటర్లతో గొలుసుకట్టుగా అనుసంధానించబడిన LinkedList ఎప్పుడు మేలైనది? లూప్‌లలో డేటాను తొలగించేటప్పుడు వచ్చే ConcurrentModificationException ను ఎలా అరికట్టాలి? అనే కీలకమైన అంశాలను ఈ పాఠంలో లోతుగా నేర్చుకుందాం.

షాపింగ్ కార్ట్ బ్యాగ్ & రైలు బోగీల అనాలజీ (The Expandable Shopping Cart Bag & Train Bogie Analogy):

  1. 1. Array vs ArrayList (పరిమిత చెక్క పెట్టె vs సాగే ఎలాస్టిక్ షాపింగ్ బ్యాగ్): సాధారణ ఎరే అనేది కేవలం 10 వస్తువులే పట్టే ఒక దృఢమైన చెక్క పెట్టె లాంటిది. 11వ వస్తువు పెడితే పెట్టె పగిలిపోతుంది (ArrayIndexOutOfBoundsException). కానీ ArrayList అనేది ఎలాస్టిక్ షాపింగ్ బ్యాగ్ లాంటిది. అందులో 10 వస్తువులు నిండగానే, తెరవెనుక JVM స్వయంగా 50% పెద్దదైన కొత్త బ్యాగ్‌ను తీసుకుని (1.5x growth), పాత వస్తువులను అందులోకి జంప్ చేయిస్తుంది. దీనివల్ల డెవలపర్‌కు సైజు గురించిన బెంగే ఉండదు!
  2. 2. ArrayList vs LinkedList (థియేటర్ సీట్లు vs గొలుసుకట్టు రైలు బోగీలు):
    • ArrayList (థియేటర్ సీట్లు): సీట్లు పక్కపక్కనే అతుక్కుని ఉంటాయి. మీ టికెట్ నంబర్ తెలిస్తే క్షణంలో సీటులో కూర్చోవచ్చు (O(1) Constant Time Lookup). కానీ మధ్యలో ఒక కొత్త వ్యక్తిని కూర్చోబెట్టాలంటే కుడివైపు ఉన్న అందరూ పక్కకు జరగాలి (O(N) Shifting Cost).
    • LinkedList (రైలు బోగీలు): ప్రతి బోగీ (Node) తన మునుపటి బోగీతో, తర్వాతి బోగీతో గొలుసులతో (Pointers: prev & next) కట్టబడి ఉంటుంది. మధ్యలో కొత్త బోగీని జోడించడం లేదా తీసేయడం క్షణంలో చేయవచ్చు (O(1) Insertion/Deletion). కానీ 50వ బోగీకి వెళ్లాలంటే మొదటి బోగీ నుండి ఒక్కొక్క బోగీ నడుచుకుంటూ వెళ్లాల్సిందే (O(N) Sequential Search)!
  3. 3. Iterator & Fail-Fast (రైలు ప్రయాణికుల టికెట్ కలెక్టర్ చెకింగ్): టికెట్ కలెక్టర్ (Iterator) బోగీలోని ప్రయాణికులను వరుసగా లెక్కిస్తున్నప్పుడు, ఎవరైనా దొంగచాటుగా మధ్యలో ఒక ప్రయాణికుడిని దింపేస్తే, కలెక్టర్ విజిల్ వేసి రైలును ఆపేస్తాడు (Fail-Fast: ConcurrentModificationException)! దీనిని నివారించడానికి ఎల్లప్పుడూ Iterator యొక్క సొంత it.remove() మెథడ్‌ను మాత్రమే వాడాలి.

ఈ పాఠం ముగిసేసరికి మీరు JCF హైరార్కీని సంపూర్ణంగా అర్థం చేసుకోవడం, Big-O ఆధారంగా సరైన లిస్ట్‌ను ఎంచుకోవడం, మరియు ఈ-కామర్స్ ఆర్డర్ ఫుల్‌ఫిల్‌మెంట్ పైప్‌లైన్ ఇంజిన్‌ను నిర్మించడంలో నిపుణులవుతారు!

1. JCF ఆవశ్యకత & ఫ్రేమ్‌వర్క్ నిర్మాణం (Java Collections Architecture)

జావా ప్రారంభంలో (Java 1.0) డేటాను సమూహాలుగా నిల్వ చేయడానికి కేవలం Arrays, Vector, Stack మరియు Hashtable మాత్రమే ఉండేవి. వీటికి ఒక ఉమ్మడి ఇంటర్‌ఫేస్ లేదా ప్రామాణిక డిజైన్ లేదు.

దీనికి సమగ్ర పరిష్కారంగా Java 1.2 లో Java Collections Framework (JCF) ప్రవేశపెట్టబడింది. JCF అనేది రెడీమేడ్ డాటా స్ట్రక్చర్లు (Lists, Sets, Maps, Queues) మరియు వాటిపై పనిచేసే ఆప్టిమైజ్డ్ అల్గారిథమ్స్ (Sorting, Searching, Shuffling) సమాహారం.

2. Collection vs Collections తేడాలు (The Crucial Plural Distinction)

జావా ఇంటర్వ్యూలలో అత్యంత ప్రాచుర్యం పొందిన తేడా:

  • Collection (ఏకవచనం - Interface): ఇది java.util ప్యాకేజీలోని రూట్ ఇంటర్‌ఫేస్. List, Set, Queue వంటి అన్ని కలెక్షన్‌లు దీనిని ఎక్స్‌టెండ్ చేసుకుంటాయి.
  • Collections (బహువచనం - Utility Class): ఇది java.util ప్యాకేజీలోని ఒక యుటిలిటీ క్లాస్. ఇందులో కలెక్షన్‌లను సార్ట్ చేయడానికి, రివర్స్ చేయడానికి, లేదా అన్‌మాడిఫైయబుల్‌గా మార్చడానికి ఉపయోగపడే స్టాటిక్ మెథడ్స్ (ఉదా: Collections.sort(), Collections.unmodifiableList()) ఉంటాయి.

3. List ఇంటర్‌ఫేస్ కాంట్రాక్ట్ & ఫీచర్లు (The Ordered List Contract)

java.util.List ఇంటర్‌ఫేస్ 3 ప్రాథమిక లక్షణాలను హామీ ఇస్తుంది:

  • 1. ఇన్సర్షన్ ఆర్డర్ సంరక్షణ (Maintains Insertion Order): అంశాలను ఏ క్రమంలో చేర్చామో అదే క్రమంలో నిల్వ చేస్తుంది.
  • 2. జీరో-బేస్డ్ ఇండెక్స్ యాక్సెస్ (Index-based Access): ఎరేల మాదిరిగానే నిర్దిష్ట ఇండెక్స్ ద్వారా అంశాలను పొందవచ్చు (list.get(index)).
  • 3. డూప్లికేట్స్ అనుమతి (Allows Duplicate Elements): ఒకే విలువను ఎన్నిసార్లయినా, అలాగే బహుళ null విలువలను నిల్వ చేసుకోవచ్చు.

4. ArrayList అంతర్గత గ్రోత్ అల్గారిథమ్ (The 1.5x Growth Formula)

ArrayList అంతర్గతంగా ఒక సాధారణ Object[] elementData ఎరేను నిర్వహిస్తుంది. డీఫాల్ట్ నో-ఆర్గ్ కన్‌స్ట్రక్టర్ new ArrayList<>() రాసినప్పుడు, మొదటి ఎలిమెంట్ చేర్చే వరకు కెపాసిటీ 0 గా ఉంటుంది; మొదటి ఎలిమెంట్ రాగానే డీఫాల్ట్ కెపాసిటీ 10 అవుతుంది.

ఆ 10 స్లాట్లు నిండిపోయినప్పుడు, JVM కొత్త సైజును ఈ క్రింది బిట్‌వైజ్ ఫార్ములాతో లెక్కిస్తుంది:

int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5x Growth!

ఉదాహరణకు: 10 + (10 / 2) = 15.
ఆ తర్వాత 15 + (15 / 2) = 22.
ఈ విధంగా ప్రతిసారీ పాత పరిమాణానికి 50% అదనపు స్థలాన్ని జోడించి కొత్త ఎరేను కేటాయించి పాత డేటాను Arrays.copyOf() ద్వారా కాపీ చేస్తుంది.

5. LinkedList డబుల్-లింక్డ్ నోడ్ ఆర్కిటెక్చర్ (Doubly-Linked Node Internals)

LinkedList లో ఎటువంటి ఎరే ఉండదు! ఇక్కడ ప్రతి డేటా అంశం ఒక స్వతంత్ర Node ఆబ్జెక్ట్ లోపల నిల్వ ఉంటుంది:

// LinkedList Internal Node Structure:
private static class Node<E> {
    E item;        // వాస్తవ డేటా
    Node<E> next;  // తర్వాతి నోడ్ మెమరీ రిఫరెన్స్
    Node<E> prev;  // మునుపటి నోడ్ మెమరీ రిఫరెన్స్
}

దీనివలన హెడ్ (ప్రారంభం) లేదా టెయిల్ (చివర) వద్ద ఎలిమెంట్లను చేర్చడం లేదా తీసేయడం మెమరీ షిఫ్టింగ్ లేకుండా O(1) లో పూర్తవుతుంది. అయితే ప్రతి నోడ్‌కు అదనంగా 2 రిఫరెన్స్ పాయింటర్లు (prev, next) ఉండటం వల్ల ArrayList కంటే 3 నుండి 4 రెట్లు ఎక్కువ మెమరీని ఆక్రమిస్తుంది!

6. ArrayList vs LinkedList: Big-O కాంప్లెక్సిటీ చార్ట్ (The Definitive Decision Matrix)

సాఫ్ట్‌వేర్ పనితీరును నిర్ణయించే ఈ క్రింది కాంప్లెక్సిటీ టేబుల్‌ను ఎల్లప్పుడూ గుర్తుంచుకోండి:

ఆపరేషన్ ArrayList LinkedList విజేత & కారణం
Random Access get(i) O(1) O(N) ArrayList (ప్రత్యక్ష ఇండెక్స్ అడ్రస్)
చివర చేర్చడం add(val) O(1) amortized O(1) ఇద్దరూ సమానం
మొదట్లో చేర్చడం add(0, val) O(N) (అన్నింటినీ జరపాలి) O(1) LinkedList (కేవలం పాయింటర్ మార్పు)
మధ్యలో తొలగించడం remove(i) O(N) O(N) (వెతకడానికి O(N)) సమానం (LinkedList కు సెర్చ్ టైమ్ పడుతుంది)
మెమరీ ఓవర్‌హెడ్ చాలా తక్కువ (Compact array) అత్యధికం (ప్రతి నోడ్‌కు 24 బైట్ల ఓవర్‌హెడ్) ArrayList విజేత

7. Iterator vs ListIterator vs for-each (Traversal Techniques)

లిస్ట్‌లోని అంశాలను చదవడానికి 3 మార్గాలు ఉన్నాయి:

  • Enhanced for-each loop: కోడ్ చదవడానికి అత్యంత సులభమైనది. కానీ లూప్ నడుస్తున్నప్పుడు ఎలిమెంట్లను తొలగించలేము.
  • Iterator: కేవలం ముందుకు మాత్రమే (Forward only) ప్రయాణించగలదు. లూప్ మధ్యలో ఎలిమెంట్లను సురక్షితంగా తొలగించడానికి it.remove() ను అందిస్తుంది.
  • ListIterator (List Exclusive): ముందుకు మరియు వెనుకకు (Bidirectional: hasPrevious(), previous()) ప్రయాణించగలదు. ఇటరేషన్ సమయంలో ఎలిమెంట్లను మార్చడానికి (set()) మరియు కొత్తవి చేర్చడానికి (add()) వీలు కల్పిస్తుంది.

8. ConcurrentModificationException నివారణ (The Fail-Fast Mechanism)

జావా కలెక్షన్లు Fail-Fast మెకానిజంను కలిగి ఉంటాయి. కలెక్షన్ లోపల modCount అనే వేరియబుల్ ఉంటుంది. మీరు లూప్ లోపల నేరుగా list.remove(i) అని పిలిస్తే, modCount మారుతుంది కానీ ఇటరేటర్ యొక్క అంతర్గత కౌంట్ మారదు. అప్పుడు జావా తక్షణమే ConcurrentModificationException విసిరి ఆపివేస్తుంది.

సరైన పరిష్కారం: లూప్‌లో ఎలిమెంట్లను తీసివేయాలంటే ఎల్లప్పుడూ iterator.remove() మాత్రమే వాడాలి, లేదా Java 8 లో వచ్చిన list.removeIf(predicate) వాడాలి!

9. డెమో 1: ArrayList vs LinkedList పర్ఫార్మెన్స్ బెంచ్‌మార్క్ (Performance Benchmark)

మొదట్లో ఇన్సర్ట్ చేయడం (Head Insertion) మరియు ఇండెక్స్ ద్వారా చదవడం (Random Lookup) లలో రెండింటి మధ్య తేడాను చూపే బెంచ్‌మార్క్:

ArrayListVsLinkedListBenchmark.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ArrayListVsLinkedListBenchmark {
    public static void main(String[] args) {
        final int ELEMENTS_COUNT = 50_000;

        System.out.println("=================================================");
        System.out.println("⚡ ARRAYLIST VS LINKEDLIST PERFORMANCE SHOWDOWN");
        System.out.println("=================================================
");

        // TEST 1: INSERTION AT HEAD (index 0)
        List<Integer> arrayList = new ArrayList<>();
        long startAl = System.currentTimeMillis();
        for (int i = 0; i < ELEMENTS_COUNT; i++) {
            arrayList.add(0, i); // Constant shifting of all elements!
        }
        long alInsertTime = System.currentTimeMillis() - startAl;

        List<Integer> linkedList = new LinkedList<>();
        long startLl = System.currentTimeMillis();
        for (int i = 0; i < ELEMENTS_COUNT; i++) {
            linkedList.add(0, i); // O(1) Pointer rewiring!
        }
        long llInsertTime = System.currentTimeMillis() - startLl;

        System.out.println("1. Head Insertion Benchmark (50,000 elements at index 0):");
        System.out.printf("   ArrayList  Insert(0):  %5d ms (Slow due to shifting)%n", alInsertTime);
        System.out.printf("   LinkedList Insert(0):  %5d ms (Fast pointer rewire)%n", llInsertTime);

        // TEST 2: RANDOM ACCESS LOOKUP (get(i))
        long startAlGet = System.nanoTime();
        int val1 = arrayList.get(25000); // Direct memory offset calculation
        long alGetTime = System.nanoTime() - startAlGet;

        long startLlGet = System.nanoTime();
        int val2 = linkedList.get(25000); // Traverses 25,000 node pointers!
        long llGetTime = System.nanoTime() - startLlGet;

        System.out.println("
2. Random Access Benchmark (get(25000) from middle):");
        System.out.printf("   ArrayList  get(25000): %5d ns (O(1) Instant Lookup)%n", alGetTime);
        System.out.printf("   LinkedList get(25000): %5d ns (O(N) Sequential Walk)%n", llGetTime);

        System.out.println("
=================================================");
        System.out.println("✅ Verdict: ArrayList wins 95% of cases; LinkedList only for Queue/Deque!");
        System.out.println("=================================================");
    }
}
Terminal Output:
=================================================
⚡ ARRAYLIST VS LINKEDLIST PERFORMANCE SHOWDOWN
=================================================

1. Head Insertion Benchmark (50,000 elements at index 0):
   ArrayList  Insert(0):    328 ms (Slow due to shifting)
   LinkedList Insert(0):      4 ms (Fast pointer rewire)

2. Random Access Benchmark (get(25000) from middle):
   ArrayList  get(25000):  1200 ns (O(1) Instant Lookup)
   LinkedList get(25000): 480200 ns (O(N) Sequential Walk)

=================================================
✅ Verdict: ArrayList wins 95% of cases; LinkedList only for Queue/Deque!
=================================================

10. డెమో 2: Iterator Safe Removal & Fail-Fast డెమో (Safe Removal)

లూప్‌లో నేరుగా list.remove() పిలిచినప్పుడు వచ్చే క్రాష్ మరియు iterator.remove() ఎలా కాపాడుతుందో చూపే డెమో:

IteratorFailFastSafeRemovalDemo.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorFailFastSafeRemovalDemo {
    public static void main(String[] args) {
        System.out.println("=================================================");
        System.out.println("🛡️ ITERATOR FAIL-FAST VS SAFE REMOVAL DEMO");
        System.out.println("=================================================
");

        List<String> badList = new ArrayList<>(List.of("Apple", "Banana", "Cherry", "Date"));

        // 1. Unsafe Removal triggering ConcurrentModificationException
        System.out.println("1. Attempting list.remove() inside enhanced for-each loop...");
        try {
            for (String fruit : badList) {
                if (fruit.equals("Banana")) {
                    badList.remove(fruit); // ❌ Unsafe removal alters modCount!
                }
            }
        } catch (Exception e) {
            System.out.println("   🚨 CRASH CAUGHT: " + e.getClass().getName());
        }

        // 2. Safe Removal using Iterator
        System.out.println("
2. Performing Safe Removal using Iterator.remove()...");
        List<String> safeList = new ArrayList<>(List.of("Apple", "Banana", "Cherry", "Date"));
        Iterator<String> it = safeList.iterator();

        while (it.hasNext()) {
            String fruit = it.next();
            if (fruit.equals("Banana")) {
                it.remove(); // ✅ Safe removal maintains synchrony!
                System.out.println("   Removed: " + fruit);
            }
        }
        System.out.println("   Final Safe List: " + safeList);

        // 3. Modern Java 8 removeIf() idiom
        System.out.println("
3. Modern Java 8 list.removeIf() idiom:");
        List<String> modernList = new ArrayList<>(List.of("Java", "C++", "Python", "Rust"));
        modernList.removeIf(lang -> lang.startsWith("C"));
        System.out.println("   Final List without 'C': " + modernList);

        System.out.println("
=================================================");
        System.out.println("=================================================");
    }
}
Terminal Output:
=================================================
🛡️ ITERATOR FAIL-FAST VS SAFE REMOVAL DEMO
=================================================

1. Attempting list.remove() inside enhanced for-each loop...
   🚨 CRASH CAUGHT: java.util.ConcurrentModificationException

2. Performing Safe Removal using Iterator.remove()...
   Removed: Banana
   Final Safe List: [Apple, Cherry, Date]

3. Modern Java 8 list.removeIf() idiom:
   Final List without 'C': [Java, Python, Rust]

=================================================
=================================================

11. Capstone ప్రాజెక్ట్: ఈ-కామర్స్ ఆర్డర్ ఫుల్‌ఫిల్‌మెంట్ పైప్‌లైన్ ఇంజిన్

ఈ అధ్యాయంలో నేర్చుకున్న అన్ని కాన్సెప్టులను (JCF ఆర్కిటెక్చర్, ArrayList ఇండెక్స్డ్ క్యాచింగ్, LinkedList FIFO క్యూయింగ్, మరియు ఇటరేటర్లు) సమగ్రంగా మిళితం చేస్తూ ఒక ప్రొడక్షన్-గ్రేడ్ E-Commerce Order Fulfillment & Dispatcher Engine ను నిర్మిద్దాం:

EcommerceOrderFulfillmentEngine.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class EcommerceOrderFulfillmentEngine {

    public record CustomerOrder(String orderId, String customer, double amount, boolean isPriority) {}

    public static class WarehouseFulfillmentCenter {
        // LinkedList used as efficient FIFO Processing Queue (O(1) poll from head)
        private final LinkedList<CustomerOrder> dispatchQueue = new LinkedList<>();
        // ArrayList used for fast indexed completed ledger lookups (O(1) random access)
        private final ArrayList<CustomerOrder> completedLedger = new ArrayList<>();

        public void receiveOrder(CustomerOrder order) {
            if (order.isPriority()) {
                dispatchQueue.addFirst(order); // VIP express order pushed to front!
                System.out.println("⚡ [PRIORITY EXPRESS] Order pushed to FRONT: " + order.orderId());
            } else {
                dispatchQueue.addLast(order); // Standard order queued at back
                System.out.println("📦 [STANDARD QUEUED] Order added to back:   " + order.orderId());
            }
        }

        public void processNextOrder() {
            if (dispatchQueue.isEmpty()) {
                System.out.println("ℹ️ No pending orders to fulfill.");
                return;
            }
            CustomerOrder processed = dispatchQueue.removeFirst(); // O(1) removal from head
            completedLedger.add(processed); // O(1) append to ledger
            System.out.printf("  🚚 Dispatched: [%s] to %s (₹%,.2f)%n",
                    processed.orderId(), processed.customer(), processed.amount());
        }

        public void printWarehouseStatus() {
            System.out.println("
-------------------------------------------------");
            System.out.println("🏭 WAREHOUSE FULFILLMENT TELEMETRY METRICS");
            System.out.println("   Pending in Queue (LinkedList):  " + dispatchQueue.size());
            System.out.println("   Completed Ledger (ArrayList):   " + completedLedger.size());
            System.out.println("-------------------------------------------------");
        }
    }

    public static void main(String[] args) {
        System.out.println("=================================================");
        System.out.println("🛒 E-COMMERCE WAREHOUSE ORDER PIPELINE");
        System.out.println("=================================================
");

        WarehouseFulfillmentCenter warehouse = new WarehouseFulfillmentCenter();

        warehouse.receiveOrder(new CustomerOrder("ORD-101", "Balaji", 2500.0, false));
        warehouse.receiveOrder(new CustomerOrder("ORD-102", "Suresh", 1200.0, false));
        // Priority order skips the line!
        warehouse.receiveOrder(new CustomerOrder("ORD-VIP-999", "Karthik Verma", 85000.0, true));

        System.out.println("
Processing Warehouse Dispatch Queue:");
        warehouse.processNextOrder(); // Should process VIP-999 first!
        warehouse.processNextOrder(); // Processes ORD-101
        warehouse.processNextOrder(); // Processes ORD-102

        warehouse.printWarehouseStatus();

        System.out.println("=================================================");
    }
}
Terminal Output:
=================================================
🛒 E-COMMERCE WAREHOUSE ORDER PIPELINE
=================================================

📦 [STANDARD QUEUED] Order added to back:   ORD-101
📦 [STANDARD QUEUED] Order added to back:   ORD-102
⚡ [PRIORITY EXPRESS] Order pushed to FRONT: ORD-VIP-999

Processing Warehouse Dispatch Queue:
  🚚 Dispatched: [ORD-VIP-999] to Karthik Verma (₹85,000.00)
  🚚 Dispatched: [ORD-101] to Balaji (₹2,500.00)
  🚚 Dispatched: [ORD-102] to Suresh (₹1,200.00)

-------------------------------------------------
🏭 WAREHOUSE FULFILLMENT TELEMETRY METRICS
   Pending in Queue (LinkedList):  0
   Completed Ledger (ArrayList):   3
-------------------------------------------------
=================================================

12. ప్రొడక్షన్ పిట్‌ఫాల్స్, బెస్ట్ ప్రాక్టీసెస్ & 5 క్విజ్‌లు (Best Practices & Quizzes)

🚫 ప్రొడక్షన్‌లో నివారించాల్సిన 4 ఘోరమైన తప్పులు (Production Pitfalls):

  1. ప్రతిచోటా LinkedList ను వాడటం: చాలామంది LinkedList లో పాయింటర్లు ఉంటాయి కాబట్టి వేగవంతం అనుకుంటారు. కానీ మెమరీ లోకాలిటీ (CPU Cache lines) లేకపోవడం మరియు అధిక మెమరీ ఓవర్‌హెడ్ వల్ల 95% సందర్భాలలో ArrayList మాత్రమే వేగవంతమైనది!
  2. ArrayList ప్రారంభ పరిమాణాన్ని అంచనా వేయకపోవడం: లక్ష అంశాలు వచ్చే లిస్ట్‌ను new ArrayList<>() తో మొదలుపెడితే అది పదే పదే 1.5 రెట్లు విస్తరిస్తూ అనేక ఎరే కాపీలను చేస్తుంది. ముందే new ArrayList<>(100000) అని ఇవ్వడం మంచిది.
  3. సాధారణ for-each లూప్‌లో ఎలిమెంట్స్ డిలీట్ చేయడం: ఇది తక్షణమే ConcurrentModificationException కు దారితీస్తుంది. removeIf() వాడాలి.
  4. లెగసీ Vector మరియు Stack క్లాసులను వాడటం: ఇవి పాతకాలపు Java 1.0 క్లాసులు; వీటిలోని ప్రతి మెథడ్‌పై సింక్రనైజ్డ్ లాక్ ఉంటుంది. వీటికి బదులుగా ArrayList మరియు ArrayDeque వాడాలి.

✨ ప్రొడక్షన్ గోల్డెన్ రూల్స్ (Golden Rules):

1. ఇంటర్‌ఫేస్ టైప్ డిక్లరేషన్: ఎల్లప్పుడూ List<String> list = new ArrayList<>(); రూపంలో డిక్లేర్ చేయండి.
2. డీఫాల్ట్ చాయిస్: సాధారణ లిస్ట్‌ల కోసం ఎల్లప్పుడూ ArrayList నే మొదటి ప్రాధాన్యతగా తీసుకోండి.
3. Queue / Deque కోసం: ప్రారంభంలో లేదా చివర తరచూ చేర్చాల్సి వస్తేనే LinkedList లేదా ArrayDeque ఎంచుకోండి.
4. ఇమ్మ్యుటబుల్ లిస్ట్‌లు: మారకూడని స్థిర లిస్ట్‌ల కోసం ఆధునిక జావా 9+ List.of("A", "B") వాడండి.

🧠 మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes):

ప్రశ్న 1: ArrayList నిండిపోయినప్పుడు దాని కొత్త సైజు ఎంత పెరుగుతుంది?

సమాధానం: పాత పరిమాణం కంటే 50% (సుమారు 1.5 రెట్లు) పెరుగుతుంది (ఫార్ములా: oldCapacity + (oldCapacity >> 1)).

ప్రశ్న 2: ArrayList లో నిర్దిష్ట ఇండెక్స్ వద్ద ఉన్న ఎలిమెంట్‌ను పొందడానికి (get(i)) టైమ్ కాంప్లెక్సిటీ ఎంత?

సమాధానం: O(1) (Constant Time).

ప్రశ్న 3: LinkedList అంతర్గతంగా ఏ ఆర్కిటెక్చర్‌ను ఉపయోగిస్తుంది?

సమాధానం: Doubly-Linked List (ప్రతి నోడ్‌కు prev మరియు next పాయింటర్లు ఉంటాయి).

ప్రశ్న 4: సాధారణ for-each లూప్ లోపల 'list.remove()' పిలిస్తే ఏ ఎక్సెప్షన్ వస్తుంది?

సమాధానం: java.util.ConcurrentModificationException (Fail-Fast మెకానిజం).

ప్రశ్న 5: ListIterator మరియు Iterator మధ్య ప్రధాన వ్యత్యాసం ఏమిటి?

సమాధానం: Iterator కేవలం ముందుకు మాత్రమే వెళ్లగలదు; ListIterator ముందుకు మరియు వెనుకకు (Bidirectional) రెండింటికీ ప్రయాణించగలదు.

← మునుపటి పాఠం: 20. Exceptions & Custom Errors తర్వాతి పాఠం: 22. Set & Map Deep Dive →