2010-12-31 35 views
7

Chúng tôi được dạy rằng ArrayList của Java kém hiệu quả hơn cho các số nguyên, vì danh sách thực sự chứa các con trỏ, trong khi một mảng int có chứa các số nguyên tại chỗ, do đó tránh phân bổ bộ nhớ và truy cập.ArrayList <Integer> được tối ưu hóa bởi JDK để thực hiện như int []?

Câu hỏi của tôi là liệu trình biên dịch JDK/JIT có tối ưu hóa loại không hiệu quả này không? Nó có tất cả các thông tin để kết luận những triển khai này có chức năng tương đương, vì vậy nó cũng có thể thay thế ArrayList với một thực hiện được hỗ trợ int [] dưới mui xe.

+0

@ 01 - hoàn toàn đồng ý về thẻ 'tối ưu hóa sớm' - đây chỉ là cuộc thảo luận lý thuyết mà tất cả chúng ta đều thích làm đôi khi. – ripper234

Trả lời

11

Không, không thể, vì bạn có thể lưu null trong danh sách ArrayList.

EDIT: Ồ, và nó cũng không thể vì generics bị xóa tại thời gian biên dịch - tại thời gian chạy, JRE không thể phân biệt ArrayLists theo loại phần tử của chúng. IOW, nó tệ hơn chỉ là null - bạn có thể lưu trữ bất kỳ đối tượng nào trong một ArrayList<Integer>.

+0

Về mặt lý thuyết, một trình biên dịch/thời gian chạy Java trong tương lai có thể loại bỏ kiểu đúc, nhưng vấn đề 'null' là một trình chặn vĩnh viễn để chuyển tất cả các cách thành' int [] '. Hơn nữa, tôi biết khá nhiều mã mà lưu trữ null trong arraylists, vì vậy nó không phải là một cái gì đó mà có khả năng để có thể biến mất. –

+1

@Donal Fellows. null luôn luôn nâng cao các vấn đề trong java. Trong trường hợp này, có thể sử dụng bit bit để lưu trữ thuộc tính isNull. Vì vậy, chúng ta có thể sử dụng một int [] dài hơn để lưu trữ tất cả thông tin từ ArrayList sign

+0

Vấn đề tiếp theo sẽ là chuyển * Integer get (int) * thành * int get (int) * automagically để tránh autoboxing trên mọi cuộc gọi !. (Giết phần lớn lợi ích hiệu năng mà tôi nghi ngờ) –

3

Nó có thể về mặt lý thuyết nhưng không. Nó có thể không hiệu quả hơn trừ khi auto-boxing cũng có thể được tối ưu hóa.

Thay vào đó, bạn có thể http://trove4j.sourceforge.net/javadocs/gnu/trove/TIntArrayList.html kết thúc tốt đẹp int [].

+0

Vâng, tôi quen thuộc với trove, đây là một câu hỏi lý thuyết. +1 anyway. – ripper234

+0

@ ripper234, tôi muốn họ hỗ trợ Danh sách ít nhất. Tự động phát hiện sẽ là lý tưởng, nhưng họ vẫn chưa có phân tích thoát cơ bản. : P –

+0

Nhưng điều đó sẽ không hoạt động vì 'int' không liên quan đến kiểu' Object'. Mặc dù hệ thống chung có thể được thiết kế để hỗ trợ loại điều này, nó sẽ liên quan đến một sự thay đổi lớn hơn nhiều đối với hệ thống bộ nạp lớp so với các nhà phát triển ngôn ngữ có thể dạ dày. Xét cho cùng, Java là * cố ý * ít phức tạp hơn C++. –

-3

Vì vậy, việc thực hiện các mảng như vậy có thể như thế này

 
import java.util.AbstractList; 
import java.util.List; 
import java.util.RandomAccess; 

public class IntArrayList extends AbstractList<Integer> 
implements List<Integer> , RandomAccess /* todo , Cloneable, java.io.Serializable */{ 

    private static final int INT_SIZE_MINUS_ONE = 15; 
    private static final int RIGHT_SHIFT = 4; 

    private int size; 
    private int isNull[]; 
    private int data[]; 

    IntArrayList(int size) { 
     if (size < 0) { 
      throw new RuntimeException("invalid size"); 
     } 
     this.size = size; 
     isNull = new int[(size + INT_SIZE_MINUS_ONE) >>> RIGHT_SHIFT]; 
     data = new int[size]; 
    } 

    private void rangeCheck(int index) { 
     if (index < 0 || index >= size) { 
      throw new IndexOutOfBoundsException(); 
     } 
    } 

    public Integer set(int index, Integer element) { 
     rangeCheck(index); 

     Integer oldValue = get(index); 
     if (element == null) { 
      isNull[index >>> RIGHT_SHIFT] &= ~(1 << (index & INT_SIZE_MINUS_ONE)); 
     } else { 
      isNull[index >>> RIGHT_SHIFT] |= (1 << (index & INT_SIZE_MINUS_ONE)); 
      data[index] = element; 
     } 
     return oldValue; 
    } 

    @Override 
    public Integer get(int index) { 
     rangeCheck(index); 
     if ((isNull[index >>> RIGHT_SHIFT] & (1 << (index & INT_SIZE_MINUS_ONE))) == 0) { 
      return null; 
     } 
     return new Integer(data[index]); 
    } 

    @Override 
    public int size() { 
     return size; 
    } 

    public boolean isEmpty() { 
     return size == 0; 
    } 
} 

Nó có thể được sử dụng bất cứ nơi nào như List<Integer>

loại như vậy của đối tượng có thể hữu ích cho việc lưu trữ lâu dài của thông tin mà ít được sử dụng. Nó sẽ làm giảm sự phân mảnh của đống với chi phí phát sinh rác tăng lên khi tiếp cận các yếu tố.

+0

Thực sự tại sao downvote? Nếu câu trả lời của tôi là hoàn toàn không chính xác, xin vui lòng, cho tôi một điểm. – sign

+0

Vì đó không phải là câu trả lời cho câu hỏi của tôi. Tôi biết cách thực hiện IntArray hiệu quả. – ripper234

Các vấn đề liên quan