Ho un enigma che mi ha indotto a riflettere se esistono classi standard Java che implementano Iterable<T>
senza implementare anche Collection<T>
. Sto implementando un'interfaccia che mi richiede di definire un metodo che accetti uno Iterable<T>
, ma l'oggetto che sto usando per supportare questo metodo richiede uno Collection<T>
.Esistono classi standard Java che implementano Iterable senza implementare Collection?
Questo mi ha fatto fare un po 'di codice molto sensato che fornisce alcuni avvisi non controllati quando compilati.
public ImmutableMap<Integer, Optional<Site>> loadAll(
Iterable<? extends Integer> keys
) throws Exception {
Collection<Integer> _keys;
if (keys instanceof Collection) {
_keys = (Collection<Integer>) keys;
} else {
_keys = Lists.newArrayList(keys);
}
final List<Site> sitesById = siteDBDao.getSitesById(_keys);
// snip: convert the list to a map
Cambiare la mia collezione risultante di utilizzare la più generified Collection<? extends Integer>
tipo non elimina l'avvertimento incontrollato per quella linea. Inoltre, non posso modificare la firma del metodo per accettare uno Collection
anziché uno Iterable
perché in quel momento non sostituisce più il metodo super e non viene richiamato quando necessario.
C'è doesn't seem to be a way around questo problema cast-or-copy: altre domande sono state poste qui e altrove e sembra profondamente radicata nei sistemi di cancellazione generica e di tipo Java. Ma sto chiedendo invece se ci sono mai delle classi che possono implementare Iterable<T>
che non implementano anche Collection<T>
? Ho dato un'occhiata allo Iterable
JavaDoc e sicuramente tutto quello che mi aspetto di passare alla mia interfaccia sarà in realtà una raccolta. Mi piacerebbe usare una classe pre-scritta in-the-wild, invece, sembra molto più probabile che sia passata come parametro e renderebbe l'unità test molto più preziosa.
Sono certo che il pezzo di cast-or-copy che ho scritto funzioni con i tipi che sto usando per il mio progetto a causa di alcuni test unitari che sto scrivendo. Ma mi piacerebbe scrivere un test unitario per alcuni input che è un iterable ma non è una raccolta e finora tutto ciò che sono riuscito a realizzare è l'implementazione di un'implementazione di una classe fittizia.
Per i curiosi, il metodo sto implementando è Guava di CacheLoader<K, V>.loadAll(Iterable<? extends K> keys)
e il metodo di supporto è un JDBI istanziata oggetto di accesso ai dati, che richiede una raccolta da utilizzare come il tipo di parametro per l'interfaccia @BindIn
. Penso di essere nel giusto pensando che questo sia tangente alla domanda, ma nel caso qualcuno voglia provare il pensiero laterale sul mio problema. Sono consapevole che potrei semplicemente biforcare il progetto JDBI e riscrivere l'annotazione @BindIn
per accettare un iterabile ...
Per rispondere alla domanda nel titolo: Sì [ 'ServiceLoader'] (https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) per esempio. – aioobe
Cosa c'è di sbagliato nel fare una copia, cioè creare una nuova collezione? Dovresti copiare solo riferimenti, non creare nuovi oggetti. – VGR
Niente di terribilmente sbagliato, ma stavo cercando un modo per evitare di fare assegnazioni. Come suggerisce il nome, ['Lists.newArrayList'] (http://grepcode.com/file/repo1.maven.org/maven2/com.google.guava/guava/r06/com/google/common/collect/Lists .java # Lists.newArrayList% 28java.lang.Iterable% 29) può allocare un nuovo array, potenzialmente 'log (n)' volte in quanto non ottiene una dimensione prima di allocare l'array di supporto. (Anche se guardo di nuovo il codice Guava, ho appena realizzato che il mio 'instanceof then cast' è ridondante.) –