Supposons que j'ai une collection de type inconnu. Ce que je veux faire, c'est le diffuser, faites-le des trucs sur le flux et récupérez-le dans le même type de collection que ma collection d'origine. Par exemple: L'idée de cet exemple de code incomplète est de renvoyer une liste code> si
col code> est de la liste
Code> Classe (ou sous-classe de celui-ci), un
SET CODE> Si
COL code> est de
SET code> classe, etc ... le nom de la méthode et réel Les opérations sur le flux ici ne sont pas importantes, je leur ai spécifié juste pour illustrer ma question.
Alors, est-ce possible? p> p>
3 Réponses :
Il n'est pas possible sans violer le principe sur lequel le cadre de flux Java a été construit sur. Cela violerait complètement l'idée d'abstraction du flux de sa représentation physique.
La séquence d'opérations de données en vrac va dans un pipeline em>, voir la photo suivante:
p> Le flux est similaire à la CAT de Schrödinger - Il n'est pas matérialisé tant que vous appelez l'opération terminale. La manipulation du flux est complètement abstraite et détachée de la source de flux d'origine. P> p> Si vous souhaitez travailler si de bas niveau avec votre stockage de données d'origine, ne vous sentez pas honte simplement en évitant les flux. Ils ne sont qu'un outil, pas rien sacré. En introduisant des ruisseaux, les bonnes vieilles collections sont toujours aussi bonnes qu'elles étaient, avec une valeur ajoutée de l'itération interne - la nouvelle iTerEfer.Foreach () méthode. P> ajouté pour satisfaire votre curiosité :) p> une solution possible forte> suit. Je n'aime pas moi-même et je n'ai pas pu résoudre tous les problèmes génériques là-bas, mais cela fonctionne avec des limitations em>. P> L'idée crée un collecteur renvoyant le même type que la collection d'entrée. Cependant, toutes les collections ne fournissent pas de constructeur nullaire (sans paramètres), et sans que ce soit le classe.newinstance () méthode ne fonctionne pas. Il y a aussi le problème de la maladresse des exceptions vérifiées dans l'expression de Lambda. (Il est mentionné dans cette belle réponse ici: https://stackoverflow.com/a/22919112/28866891 ) p> Comme vous pouvez le constater, cela fonctionne en général, supposé que votre collection d'origine fournit un constructeur nullaire. P>
public void test() {
final Collection<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
final Collection<Integer> arrayList = new ArrayList<>(numbers);
final Collection<Integer> arrayList2 = getBiggerThan(arrayList, 6);
System.out.println(arrayList2);
System.out.println(arrayList2.getClass());
System.out.println();
final Collection<Integer> set = new HashSet<>(arrayList);
final Collection<Integer> set2 = getBiggerThan(set, 6);
System.out.println(set2);
System.out.println(set2.getClass());
System.out.println();
// This does not work as Arrays.asList() is of a type
// java.util.Arrays$ArrayList which does not provide a nullary constructor
final Collection<Integer> numbers2 = getBiggerThan(numbers, 6);
}
Javadoc pour getclass code>: " le type de résultat réel est
classe Étends | x |>} code> où
est l'effacement" code> est l'effacement du type statique de l'expression sur laquelle
getclass code> est appelé. i> ". Son comme vous devez vivre avec cet avertissement.
Et ce comportement a bon sens: getclass code> renvoie la classe d'exécution et au moment de l'exécution Tous les paramètres de type ont été effacés. Je pense que nous avons découvert l'une des rares utilisations appropriées des types bruts!
Il y a deux problèmes ici: (1) le type d'exécution (classe) de l'entrée et son résultat, et (2) le type de temps de compilation de l'entrée et son résultat.
pour (1) pour (1), Peut sembler étrange, mais en général, il n'est pas possible en Java de créer une copie d'une instance d'une classe arbitraire. Utilisation de pour (2), une dose appropriée de génériques peut rendre ce type de sécurité au moment de la compilation. Notez qu'il est limité de Exemples d'utilisation: P> getclass (). NewInstance () code> pourrait ne pas fonctionner si la classe n'a pas de constructeur de no-arg accessible ou s'il est immuable. L'objet peut ne pas être
clonable code> non plus. Ainsi, l'appelant doit adopter un fournisseur responsable de la création d'une instance de la bonne classe de résultat. P>
comparable
t code> de sorte que l'appelant soit limité transmettre une collection de choses comparables. Cela nous permet d'utiliser
comparèteo code> pour comparer les valeurs. Nous utilisons également la méthode
Collecteurs.tocollection.tocollection.tocollection et transmettez le fournisseur
Obtenez la méthode CODE> à celui-ci. P>
List<Integer> input1 = Arrays.asList(1, 4, 9, 13, 14, 22);
List<Integer> filtered1 = getBigger(input1, 10, ArrayList::new);
Set<String> input2 = new HashSet<>();
input2.add("foo");
input2.add("bar");
input2.add("baz");
input2.add("qux");
Set<String> filtered2 = getBigger(input2, "c", HashSet::new);
Étant donné que le type de sous-jacent réel n'est connu que la callee de votre méthode, il devrait être de sa responsabilité de collecter code> à code> la collection code> du tout type qu'ils veulent (par exemple en utilisant < Code> Collecteurs.Tocollection (CustomCollectionType :: Nouveau); code>). Donc, votre méthode devrait renvoyer flux code>. Il peut prendre
collection code> ou
flux code> en fonction de la commodité. P>
Quelles espèces voulez-vous faire sur le ruisseau? Cela signifie-t-il que vous devez avoir un format de flux spécifique?