1
votes

Comment initialiser un tableau dans Generics avec des types de données mix

Je suis en train de parcourir les tableaux Java et en plus, je suis à la recherche de génériques. Voici les deux méthodes d'initialisation d'un tableau

outcome = {7, "Tie" , 9.0};

Mais lorsque j'utilise des génériques, j'ai un mélange de types de données par exemple,

String[] outcome = {"0 wins", "Tie" , "X wins"};

Le tableau ci-dessus a un seul type de données String. Et si dans un tableau j'avais quelque chose comme ci-dessous

int[] data = {1,2,3,4,5,6,7,8,9};

// or

int[] data;
data = new int[] {1,2,3,4,5,6,7,8,9};

maintenant j'ai un mélange de types de données dans un tableau. Comment puis-je l'écrire ou s'il est possible de le faire avec des génériques? Puis-je le faire avec ArrayList?

Merci


1 commentaires

Ne mélangez pas le tableau et les génériques. Le fait que les tableaux soient covariants et conservés, alors que les génériques sont invariants et effacés, vous causera forcément des ennuis. --- Au lieu de mélanger différents types dans un tableau, créez une classe qui représente votre résultat.


6 Réponses :


1
votes

Une façon de gérer cela est de créer un tableau d ' Object , qui peut accueillir tous les types de données

if(outcome[0] instanceof Integer){
   Integer i = (Integer) outcome[0];
}

Et plus tard, vous pouvez accéder à des objets tels que:

Object[] outcome = {7, "Tie" , 9.0};

et vice versa ..


3 commentaires

Donc, pour chaque type de données différent, je dois écrire la condition ci-dessus?


si vous êtes sûr du type de données, vous n'avez pas à les écrire, mais si vous n'êtes pas sûr, vous devrez


Oui. Il n'y a pas d'autre moyen si vous utilisez le type d'objet. Si vous voulez mettre des limites, utilisez des génériques.



1
votes
Object[] outcome = {7, "Tie" , 9.0};

0 commentaires

0
votes

Comme mentionné précédemment, vous pouvez utiliser un tableau Object. Vous pouvez également utiliser une classe générique. Voici un exemple:

public class Queue<E> {

    private ArrayList<E> queue;

    /**Unparametrized constructor**/
    public Queue() {
        queue = new ArrayList<E>();
    }

    /**Enqueues an element into the queue.**/
    public void enqueue(E val) {
        queue.add(val);
    }

    /**Dequeues an element from the queue.**/
    public E dequeue() {
        E output = queue.get(0);
        queue.remove(0);
        return output;
    }

    /**Gets the current size of the queue.**/
    public int size() {
        return queue.size();
    }
}

Lire sur les génériques et comment les utiliser.


0 commentaires

0
votes

Vous allez devoir créer un tableau d'objets, puisque tous les objets en java étend Object :

List<Object> listObjects = new ArrayList<Objects>();

Et pour trouver si l'objet à l'index x est (par exemple) un Integer alors vous allez devoir utiliser un cast:

int x = (Integer)arr[x]; //x could be 0 or 1 or 2

Vous pouvez également le faire avec un ArrayList :

Object[] arr = new Object[3];
//to add objects to it:

arr[0]=new String("element at index 0");
arr[1]=new Integer(1);
arr[2]=new Character('2');


0 commentaires

2
votes

Je voudrais corriger ceci:

Mais lorsque j'utilise des génériques, j'ai un mélange de types de données

Les génériques nécessitent des types de données homogènes . Par exemple, une List est une liste qui ne peut contenir qu'un Integer , et une List ne peut contenir que des Number s, qui couvrent d'autres types de nombres tels que Long , Short , Double < / code>, etc ... mais sont référencés par le simple type Number .

Quoi qu'il en soit, ce que vous recherchez est un sac - une collection qui peut contenir n'importe quel objet arbitraire. Vous pouvez l'implémenter avec un Object [] ou une List , et vous allez devoir vérifier le type de chacun élément que vous retirez lorsque vous voulez l'utiliser, car il n'y a aucun moyen en Java d'avoir un type de données hétérogène, ce que vous recherchez.


1 commentaires

Si l'OP est intéressé par une petite refonte, il y a une très bonne description d'une collection hétérogène dans Effective Java 2nd Edition.



1
votes

tl; dr: À mon avis, les tableaux ne conviennent pas au problème, vous devriez plutôt utiliser des objets.


Ce n'est pas une réponse directe à votre question, mais une réponse sous la forme de une refonte.

Tout d'abord, abordons votre déclaration sur les génériques et les tableaux. Les tableaux sont covariants et conservés, tandis que les génériques sont invariants et effacés.

  • Covariant signifie que lorsque B étend A , vous pouvez écrire A [] aArray = new B [someSize]; . Invariant signifie que ce n'est pas possible: ArrayList aList = new ArrayList (); entraînera une erreur de compilation.
  • Conservé signifie que les informations sur le type sont conservées lors de l'exécution: un tableau "sait toujours * de quel type ses éléments ont. Effacé signifie que les informations de type ont disparu après la compilation. Ceci est également appelé Effacement de type . li>

Le mélange de covaraint et conservé contre invariant et effacé a un bon potentiel pour vous causer des ennuis. C'est la raison pour laquelle ArrayList utilise un Object [] au lieu d'un T [] comme structure de données de sauvegarde .

Passons maintenant à la question réelle. Comme d'autres l'ont déjà dit, nous pourrions aller sur la route et créer un Object [] . Je déconseillerais fortement cela car nous perdons toutes les informations de type. Le seul moyen de récupérer ces informations est une vérification instanceof , qui rend votre code rigide. Imaginez que vous modifiez le type d'une entrée. Dans ce cas, l ' instanceof renverra false , conduisant éventuellement à un comportement indésirable et (dans le meilleur des cas) un test devenant rouge ou (dans le pire des cas) nous pourrions ne pas le remarquer.

Maintenant, comment contourner cela? Nous créons une classe représentant (ce que j'en déduis) des résultats de match:

public class MatchResult {
    private final int firstTeamScore;
    private final int secondTeamScore;

    public MatchResult(final int firstTeamScore, final int secondTeamScore) {
        this.firstTeamScore = firstTeamScore;
        this.secondTeamScore = secondTeamScore;
    }

    public int getFirstTeamScore() {
        return firstTeamScore;
    }

    public int getSecondTeamScore() {
        return secondTeamScore;
    }

    public String getResultForFirstTeam() {
        if (firstTeamScore > secondTeamScore) {
            return "Win"; // In an actual implementation, I would replace this with an enum
        } else if(firstTeamScore = secondTeamScore) {
            return "Tie";
        } else {
           return "Lose";
        }
    }
    // You can add a method public String getResultForSecondTeam(), I omitted it for brevity
}

Qu'avons-nous gagné? Nous avons des types. Les scores sont toujours des int , les résultats toujours des String . Si nous devions, par exemple, changer le type de getReultforFirstTeam () de String à, par exemple, un Enum , nous aurions des erreurs de compilation pour tous les emplacements où le type ne correspond plus. Ainsi, nous perfectionnons la conception fail-fast et sommes obligés de modifier le code si nécessaire . Et ainsi, nous n'avons même pas la chance d'avoir le comportement sournois et indésirable que nous avions auparavant.


0 commentaires