คำถามมาตรฐานเกิดขึ้น: จะเริ่มต้นรายการได้อย่างไร? รหัสด้านล่างจะไม่ทำงาน: มันจะส่งผลให้เกิดข้อผิดพลาดในการคอมไพล์: ชื่อ ตัวแปรท้องถิ่นอาจไม่ได้รับการ เตรียมใช้งาน ข้อกำหนดเฉพาะของ Java กำหนดให้ตัวแปรท้องถิ่นทั้งหมด (ซึ่งมีอยู่บนสแต็ก) ต้องเริ่มต้นด้วยค่าที่เหมาะสม นี่คือวิธีที่คุณสามารถทำได้: ไม่ต้องสงสัยเลยว่ารายการจะต้องเริ่มต้นได้ คุณสามารถสร้างรายการในบรรทัดแรกหรือทำบางอย่างที่ชาญฉลาดกว่าและใช้ การเริ่มต้นแบบ Lazy เหมือนที่เราทำใน เมธอด getAllNames( ) ในกรณีนี้ รายการจะถูกสร้างขึ้นเมื่อจำเป็นเท่านั้น - หากไม่ตรงตามเงื่อนไขเริ่มต้น รายการจะไม่ปรากฏบนฮีป เรามาถึงคำถามหลัก: เราควรกำหนดขนาดใดสำหรับรายการ? ทางเลือกที่ดีที่สุดคือระบุขนาดที่แน่นอนให้เขา ตัวอย่างเช่น: ในกรณีนี้ ต้องส่งคืนชื่อ nชื่อ และด้วยเหตุนี้ จึงมีการสร้างคอลเล็กชันขององค์ประกอบ n รายการ อย่างไรก็ตาม ค่าที่แน่นอนของ nไม่เป็นที่รู้จักเสมอไป แม้แต่ในตัวอย่างที่ให้มา จะเกิดอะไรขึ้นถ้า n=1000และมีชื่อให้เลือกเพียง 100 ชื่อเท่านั้น เมื่อทำงานกับคอลเลกชัน วิธีที่ได้รับความนิยมมากที่สุดคือการเรียกตัวสร้างเริ่มต้น หากคุณดูซอร์สโค้ด Java (เวอร์ชัน 1.6) อย่างที่คุณเห็น โดยค่าเริ่มต้นรายการองค์ประกอบ 10 รายการจะถูกสร้างขึ้น นั่นคือเราสามารถใช้ตัวสร้างเริ่มต้นได้อย่างปลอดภัยเมื่อเราไม่ได้วางแผนที่จะจัดเก็บองค์ประกอบมากกว่า 10 รายการในรายการ จะเกิดอะไรขึ้นถ้าคุณพยายามเพิ่มองค์ประกอบที่ 11? ไม่มีอะไรเลวร้าย... องค์ประกอบจะถูกเพิ่มสำเร็จ ดูที่วิธีการ: ขนาด ของอาร์เรย์ถูกควบคุมโดย วิธีการ SureCapacity ขนาดเพิ่มขึ้น 1.5เท่า อาร์เรย์ใหม่จะถูกสร้างขึ้นและองค์ประกอบต่างๆ จะถูกย้ายเข้าไปอยู่ในนั้น หากเราตั้งค่าขนาดเป็น 10 ดังนั้นในองค์ประกอบที่ 11:
public List
getAllNames() { List
names; if (/*необходимые условия выполнены*/) { names = new ArrayList
(); /*заполнение списка*/ } return names; }
List
names = null; List
names = new ArrayList
(); List
names = new ArrayList
(0); List
names = new ArrayList
(size);
public List
getTopNames (int n) { List
names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList
(n); /*заполнение списка*/ } return names; }
names = new ArrayList
();
/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; }
public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
- ขนาดเปลี่ยนเป็น 10 * 3/2 + 1 = 16
- เพิ่มขึ้นครั้งต่อไป = 16 * 3/2 + 1 = 25
- เพิ่มขึ้นครั้งต่อไป = 25 * 3/2 + 1 = 39 และต่อๆ ไป
- สร้างคอลเลกชันเฉพาะเมื่อคุณต้องการเท่านั้นไม่เช่นนั้นให้เริ่มต้นเป็นโมฆะหรือใช้Collections.EMPTY_LIST
- หากคุณทราบขนาดที่แน่นอนที่ต้องการให้ระบุในตัวสร้างคอลเลกชัน
- หากคุณแน่ใจว่าจำนวนองค์ประกอบจะไม่เกิน 10 คุณสามารถใช้ตัวสร้างเริ่มต้นได้ตามสบาย
- ความเสี่ยงที่เกี่ยวข้องกับการสร้างคอลเลกชันขนาดศูนย์คือความถี่ในการสร้างอาร์เรย์ใหม่และการคัดลอกข้อมูลอาจสูงขึ้น คุณต้องคิดอย่างรอบคอบว่าการใช้คอลเลกชันขนาดศูนย์จะมีประโยชน์มากหรือไม่
- หากคุณเริ่มต้นคอลเลกชันที่มีขนาดใหญ่เกินไปที่จุดเริ่มต้นของวิธีการและต้องการลดขนาดลง ก็จะมีเมธอดtrimToSize()
GO TO FULL VERSION