2010-01-17 37 views
15

Làm cách nào để lọc một mảng trong Java?Làm thế nào để lọc một mảng trong Java?

Tôi có một mảng của các đối tượng, ví dụ xe:

Class:

public class Car{ 
    public int doors; 
    public Car(int d){ 
     this.doors = d; 
    } 
} 

Sử dụng:

Car [] cars = new Cars[4]; 
cars[0] = new Car(3); 
cars[1] = new Car(2); 
cars[2] = new Car(4); 
cars[3] = new Car(6); 

Bây giờ tôi muốn lọc mảng xe, chỉ giữ lại 4 cửa ra vào và nhiều hơn nữa:

for(int i = 0; i<cars.length; i++){ 
    if(cars[i].doors > 4) 
     //add cars[i] to a new array 
    } 
} 

Tôi nên làm như thế nào?

Trước khi tôi đã làm điều đó với một Vector:

Vector subset = new Vector(); 
for(int i = 0; i<cars.length; i++){ 
    if(cars[i].doors > 4) 
     //add cars[i] to a new array 
     subset.addElement(cars[i]); 
    } 
} 

Và sau đó tôi sẽ làm cho một mảng mới với kích thước của Vector. Sau đó, tôi sẽ lặp lại vectơ một lần nữa và điền vào mảng mới. Tôi biết đây là một thủ tục rất lớn cho một cái gì đó đơn giản.

Tôi đang sử dụng J2ME.

+1

Thực sự quan trọng đối với các vùng chứa của bạn là mảng chứ không phải vectơ? Bởi vì vectơ chỉ nghe có vẻ thích hợp để sử dụng. – zneak

+1

Vâng, tôi không thể sử dụng xe Vector trong môi trường của mình. Vì vậy, tôi phải làm cho phôi tất cả các thời gian, mà có thể gặp khó khăn ... – hsmit

Trả lời

10

EDIT: thấy rằng ArrayList không có trong J2ME, nhưng dựa trên tài liệu, nó có Vector. Nếu mà lớp Vector khác với J2SE Vector (như this documentation indicates), thì có lẽ đoạn mã sau sẽ làm việc:

Vector carList = new Vector(); 
for(int i = 0; i<cars.length; i++){ 
    if(cars[i].doors > 4) 
     carList.addElement(cars[i]); 
    } 
} 
Car[] carArray = new Car[carList.size()]; 
carList.copyInto(carArray); 
+0

carList.toArray() không hoạt động trong J2ME, cảm ơn sự trợ giúp của bạn! – hsmit

+0

Tôi không nhận ra rằng Vector hoạt động khác nhau, có thể thử đoạn mã thứ hai mà tôi đã thêm vào. –

+0

bạn có thể muốn khởi tạo vectơ với cars.length. có lẽ nó sẽ hiệu quả hơn. – Bozho

1

Bạn có thể sử dụng System.arrayCopy():

Car[] cars = ... 
int length = cars.length < 4 ? cars.length() : 4; 
Car filter = new Car[4]; 
System.arrayCopy(cars, 0, filter, 0, length); 

UPDATE: System.arrayCopy có sẵn trong Java ME API, không giống như Vector.subList(). Cảm ơn vì sự đúng đắn của bạn.

+0

Tôi không nghĩ rằng tôi có thể sử dụng chúng trong J2ME ... – hsmit

+0

@hsmit, System.arrayCopy() có sẵn trong Java ME, nhưng không phải là ' Vector.subList() '. – notnoop

1

Tôi không thể thấy sai mã của bạn. Bạn có thể chỉ cần dính với Vectors trong suốt.

Bạn có thể đơn giản hóa phần thứ hai (nơi bạn sao chép các mục phù hợp vào mảng mới) bằng cách sử dụng Vector.copyInto (Object []).

2

Nếu bạn thực sự cần một mảng đơn giản, tôi nghĩ rằng cách của bạn là con đường để đi: bạn không biết số phần tử kết quả trước khi lọc và bạn không thể tạo mảng mới mà không biết số lượng các phần tử.

Tuy nhiên, nếu bạn không cần an toàn chỉ, hãy xem xét sử dụng ArrayList thay vì Vector. Nó phải nhanh hơn một chút. Sau đó sử dụng phương thức toArray của ArrayList để lấy mảng.

+0

Tôi nghĩ rằng ArrayList không được sử dụng trong J2ME không may ... – hsmit

+0

Ah, điểm tốt. Vì vậy, điều này đi xuống để lựa chọn giữa sử dụng bộ nhớ so với tốc độ: Hoặc tạo ra một Vector trung gian và nhận được mảng từ đó (nhanh nhưng mất bộ nhớ), hoặc đi qua danh sách hai lần, lần đầu tiên chỉ để tìm ra sau đó số lượng các phần tử và lần thứ hai để điền vào một mảng có kích thước đó (có thể chậm hơn, nhưng tạo ra ít rác hơn). –

+1

Không sử dụng một ArrayList, sử dụng một LinkedList nếu bạn không biết số lượng các yếu tố trước. Thêm các trường mới vào một ArrayList đắt hơn, so với một LinkedList, do cấu trúc bên trong của chúng. –

1

Không có cách nào trực tiếp để loại bỏ các yếu tố từ một mảng; kích thước của nó là cố định. Dù bạn làm gì, bạn cần phải phân bổ một mảng mới bằng cách nào đó.

Nếu bạn muốn tránh chi phí nhỏ của bộ nhớ phân bổ Vector, một tùy chọn khác là thực hiện hai lần vượt qua mảng của bạn. Lần đầu tiên, chỉ cần đếm số phần tử mà bạn muốn giữ lại. Sau đó phân bổ một mảng có kích thước và lặp lại mảng cũ của bạn, sao chép các phần tử phù hợp vào mảng mới.

+0

Vâng, nghe có vẻ thú vị. Bạn có bất kỳ ý tưởng về hiệu suất của cả hai? – hsmit

+0

Tôi sẽ * đoán * rằng cách tiếp cận của tôi có thể nhanh hơn, tùy thuộc vào mức độ phát triển của một véc tơ tốn kém so với các chu kỳ vòng lặp phụ có liên quan. Nhưng tôi không biết nhiều về đặc tính hiệu suất của J2ME, và nó cũng sẽ phụ thuộc vào mảng của bạn lớn như thế nào, v.v. Bạn phải chuẩn bị để chắc chắn. – Porculus

1

Bạn sẽ cần phải tạo một mảng mới.

Vector vector = new Vector(array.length); 

for (int i = 0; i < array.length; i++) { 
    if (array[i].doors > 4) { 
     vector.add(array[i]); 
    } 
} 

Car[] result = new Car[vector.size()]; 
vector.copyInto(result); 

Điều này không thực sự hiệu quả.

+0

Không có 'java.util.Iterator' trong Java ME: http://java.sun.com/javame/reference/apis/jsr139/ – BalusC

+0

woops :) làm thế nào mà tôi đã quên. (Đã cập nhật) – Bozho

5

Cách hiệu quả nhất để làm điều này - nếu vị bạn đang lọc trên là không tốn kém và bạn đang truy cập nó với một chủ đề duy nhất - thường là phải đi qua danh sách hai lần:

public Car[] getFourDoors(Car[] all_cars) { 
    int n = 0; 
    for (Car c : all_cars) if (c.doorCount()==4) n++; 
    Car[] cars_4d = new Car[n]; 
    n = 0; 
    for (Car c : all_cars) if (c.doorCount()==4) cars_4d[n++] = c; 
    return cars_4d; 
} 

Thao tác này duyệt qua danh sách hai lần và gọi thử nghiệm hai lần, nhưng không có phân bổ hoặc sao chép bổ sung. Các phương thức kiểu Vector đi qua danh sách một lần, nhưng phân bổ gấp đôi bộ nhớ cần (tạm thời) và sao chép mọi phần tử tốt khoảng hai lần. Vì vậy, nếu bạn đang lọc một phần nhỏ của danh sách (hoặc hiệu suất không phải là một vấn đề, mà rất thường nó không phải là), sau đó phương pháp Vector là tốt. Nếu không, phiên bản ở trên hoạt động tốt hơn.

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