Làm thế nào để truyền một ArrayList cho một tham số phương thức varargs?


235

Về cơ bản tôi có một ArrayList các vị trí:

ArrayList<WorldLocation> locations = new ArrayList<WorldLocation>();

bên dưới này tôi gọi phương thức sau:

.getMap();

các tham số trong phương thức getMap () là:

getMap(WorldLocation... locations)

Vấn đề tôi gặp phải là tôi không chắc chắn làm thế nào để vượt qua trong danh sách WHOLE của locationsphương thức đó.

Tôi đã thử

.getMap(locations.toArray())

nhưng getMap không chấp nhận điều đó bởi vì nó không chấp nhận Đối tượng [].

Bây giờ nếu tôi sử dụng

.getMap(locations.get(0));

nó sẽ hoạt động hoàn hảo ... nhưng tôi cần phải bằng cách nào đó vượt qua TẤT CẢ các vị trí ... tất nhiên tôi có thể tiếp tục thêm locations.get(1), locations.get(2)vv nhưng kích thước của mảng khác nhau. Tôi chỉ không sử dụng cho toàn bộ khái niệm về mộtArrayList

Điều gì sẽ là cách dễ nhất để đi về điều này? Tôi cảm thấy như bây giờ tôi không nghĩ thẳng.


Câu trả lời:


339

Nguồn bài viết: Truyền danh sách làm đối số cho phương thức vararg


Sử dụng toArray(T[] arr)phương pháp.

.getMap(locations.toArray(new WorldLocation[locations.size()]))

( toArray(new WorldLocation[0])cũng hoạt động, nhưng bạn sẽ phân bổ một mảng có độ dài bằng không mà không có lý do.)


Đây là một ví dụ hoàn chỉnh:

public static void method(String... strs) {
    for (String s : strs)
        System.out.println(s);
}

...
    List<String> strs = new ArrayList<String>();
    strs.add("hello");
    strs.add("wordld");

    method(strs.toArray(new String[strs.size()]));
    //     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

1
Làm thế nào tốn kém hoạt động này sẽ được về bộ nhớ và tốc độ?
mindreader

Điều này sẽ không hoạt động mà không có cảnh báo nếu có thêm các mẫu liên quan. Ví dụ, someMethod(someList.toArray(new ArrayList<Something>[someList.size()]))sẽ đưa ra một cảnh báo rất khó chịu nếu hàm này dài hơn một vài dòng (vì bạn có thể triệt tiêu nó cho toàn bộ hàm hoặc bạn phải tạo mảng trong một bước bổ sung và chặn cảnh báo về biến bạn lưu trữ nó.
Qw3ry

23
Rõ ràng cách tiếp cận nhanh nhất là cho kích thước bằng 0 thay vì kích thước của mảng. Nói tóm lại, đó là vì hằng số thời gian biên dịch cho phép sử dụng một phương thức tối ưu hóa. shipilev.net/blog/2016/arrays-wisdom-ancents
geg

2
@JoshM. Java cần rất nhiều thứ. ;) Tôi cũng (đến từ nền C #) bỏ lỡ các toán tử chỉ mục. Làm việc với từ điển trong C # trơn tru hơn nhiều so với làm việc với HashMaps trong Java.
Per Lundberg

@PerLundberg - Hoàn toàn đồng ý. Ngoài ra, một nhà phát triển C # chủ yếu hiện đang làm việc với w / Java8. Có lẽ 10/11 sẽ tốt hơn. :-P
Josh M.

42

Trong Java 8:

List<WorldLocation> locations = new ArrayList<>();

.getMap(locations.stream().toArray(WorldLocation[]::new));

2
đây là java voodoo, nhưng tốt hơn java (8) voodoo .. cảm ơn!
granadaCoder

locations.toArray(WorldLocations[]::new)dường như cũng hoạt động kể từ java 11 (Không có .stream())
Eran Medan

12

Một phiên bản ngắn hơn của câu trả lời được chấp nhận bằng Guava:

.getMap(Iterables.toArray(locations, WorldLocation.class));

có thể rút ngắn hơn nữa bằng cách nhập tĩnh vàoArArray:

import static com.google.common.collect.toArray;
// ...

    .getMap(toArray(locations, WorldLocation.class));

1

Bạn có thể làm:

getMap(locations.toArray(new WorldLocation[locations.size()]));

hoặc là

getMap(locations.toArray(new WorldLocation[0]));

hoặc là

getMap(new WorldLocation[locations.size()]);

@SuppressWarnings("unchecked") là cần thiết để loại bỏ cảnh báo ide.


1
Giải pháp thứ 2 tốt hơn!
bò tót
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.