Jak przekazać ArrayList do parametru metody varargs?


236

Zasadniczo mam ArrayList lokalizacji:

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

poniżej nazywam następującą metodę:

.getMap();

parametry w metodzie getMap () to:

getMap(WorldLocation... locations)

Problem, który mam, polega na tym, że nie jestem pewien, jak przekazać CAŁĄ listę locationsdo tej metody.

próbowałem

.getMap(locations.toArray())

ale getMap tego nie akceptuje, ponieważ nie akceptuje Objects [].

Teraz jeśli użyję

.getMap(locations.get(0));

będzie działał idealnie ... ale muszę jakoś przekazać WSZYSTKIE lokalizacje ... Oczywiście mógłbym nadal dodawać locations.get(1), locations.get(2)itd., ale rozmiar tablicy jest różny. Po prostu nie jestem przyzwyczajony do całej koncepcjiArrayList

Jaki byłby najłatwiejszy sposób na to? Czuję, że po prostu nie myślę teraz.


Odpowiedzi:


340

Artykuł źródłowy: Przekazywanie listy jako argumentu do metody vararg


Skorzystaj z toArray(T[] arr)metody

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

( toArray(new WorldLocation[0])działa również, ale bez powodu przydzielisz tablicę o zerowej długości).


Oto kompletny przykład:

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
Jak kosztowna byłaby ta operacja pod względem pamięci i szybkości?
mindreader

To nie zadziała bez ostrzeżenia, jeśli w grę wchodzą kolejne szablony. Np. Wyświetli someMethod(someList.toArray(new ArrayList<Something>[someList.size()]))ostrzeżenie, które jest bardzo irytujące, jeśli funkcja ma więcej niż kilka wierszy (ponieważ możesz albo ją wyłączyć dla całej funkcji, albo musisz utworzyć tablicę w dodatkowym kroku i wyłączyć ostrzeżenie dla zmiennej przechowuj
Qw3ry,

23
Najwyraźniej najszybszym podejściem jest podanie rozmiaru zero zamiast rozmiaru tablicy. Krótko mówiąc, ponieważ stała czasowa kompilacji umożliwia stosowanie zoptymalizowanej metody. shipilev.net/blog/2016/arrays-wisdom-ancients
geg

2
@JoshM. Java potrzebuje wielu rzeczy. ;) Ja także (pochodząc z języka C #) brakuje operatorów indeksu. Praca ze słownikami jest znacznie płynniejsza w C # niż praca z HashMaps w Javie.
Per Lundberg,

@PerLundberg - Całkowicie się zgadzam. Również przede wszystkim programista C # obecnie pracujący w / Java8. Może 10/11 będzie lepiej. :-P
Josh M.

42

W Javie 8:

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

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

2
to jest java voodoo, ale lepiej java (8) voodoo .. dzięki!
granadaCoder,

locations.toArray(WorldLocations[]::new)wydaje się również działać od czasu wydania java 11 (bez .stream())
Eran Medan

12

Krótsza wersja zaakceptowanej odpowiedzi przy użyciu Guava:

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

można dodatkowo skrócić, importując statycznie do Array:

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

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

1

Możesz to zrobić:

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

lub

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

lub

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

@SuppressWarnings("unchecked") jest potrzebny do usunięcia ostrzeżenia ide.


1
Drugie rozwiązanie jest lepsze!
gaurav
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.