Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Initialisation de tableau

13 réponses
Avatar
Pierre Maurette
Bonjour,

C'est kôr moi avec mes questions de newbie ;-)
Je dois dire que je suis assez pollué par le C (plus que le C++) et
éventuellement le Php. La question du jour est un tout petit détail,
mais la réponse devrait m'aider à mieux percevoir le langage.
Dans une classe, j'ai:

public class Case
extends Canvas {
/* .... */
private boolean[][] matrice_;
/* .... */

matrice_ est normalement initialisée dans le constructeur:

matrice_ = new boolean[7][5];

On doit parfois réinitialiser matrice_, tout à false. Je trouve ça (le
code est de mon fils, je le "corrige[*]", MDR, c'est un peu les
Aveugles dans le tableau de Bruegel !) :

[*] pas le fiston, le code ...

public void reset() {
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 5; j++) {
matrice_[i][j] = false;
}
}
}

Puis-je remplacer par:

public void reset() {
matrice_ = new boolean[7][5];
}

Le fait que new initialise tout à false, je ne fait que le supposer, et
je l'ai vérifié. Est-ce garanti ?

Recréer un objet a-t-il des effets néfastes ?

Existe-t-il d'autres méthodes de "remise à zéro" ou de "mise à X"
massives ?

Merci d'avance ....

--
Pierre Maurette

10 réponses

1 2
Avatar
Insitu

public void reset() {
matrice_ = new boolean[7][5];
}

Le fait que new initialise tout à false, je ne fait que le supposer,
et je l'ai vérifié. Est-ce garanti ?


Oui, c'est garanti par les valeurs par défauts des types primitifs.
cf. la section 4.12.5 Initial Values of Variables


Recréer un objet a-t-il des effets néfastes ?


a part encombrer la mémoire tant que le garbage collector ne s'est pas
execute et le cout d'allocation du nouvel objet, aucun. Dans ce cas
précis, je ne suis pas sur que la reinitialisation du tableau ne soit
pas moins couteuse.

insitu.

Avatar
Hervé AGNOUX
Pierre Maurette wrote:

Bonjour,

C'est kôr moi avec mes questions de newbie ;-)
Je dois dire que je suis assez pollué par le C (plus que le C++) et
éventuellement le Php. La question du jour est un tout petit détail,


Ce ne sont pas des pollutions : il s'agit juste d'autres technologies ; tout
est bon à prendre.



public void reset() {
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 5; j++) {
matrice_[i][j] = false;
}
}
}



Ce n'est pas excellent, mais c'est correct. Peut être pourriez-vous faire :

for (int i = 0; i < matrice.length; i++) {
for (int j = 0; j < matrice[i].length; j++) {


Puis-je remplacer par:

public void reset() {
matrice_ = new boolean[7][5];
}



Non. Vous devez, d'abord, créer votre tableau par "new", puis l'initialiser
par votre boucle for.


Le fait que new initialise tout à false, je ne fait que le supposer, et
je l'ai vérifié. Est-ce garanti ?



Oui, new initialise tout à false, c'est garanti par
http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.5
(4.12.5 Initial Values of Variables).


Recréer un objet a-t-il des effets néfastes ?



Bien sûr ! Cela rend sourd !


Existe-t-il d'autres méthodes de "remise à zéro" ou de "mise à X"
massives ?



Si vous devez le faire souvent, vous pouvez préparer un tableau de valeurs
initiales, sorte de constante, que vous copiez ensuite dans le tableau que
vous voudrez utiliser par System.arrayCopy.

Vous pouvez également utiliser des java.nio.Buffer en jonglant avec les bits
(il n'y en a pas de spéciaux pour les booléens). Si vous venez du C, cela
ne devrait pas vous poser de problèmes. Néanmoins, même d'un point de vue
java, cela demande un peu plus de technique. Il vaut mieux, dans un premier
temps, se familiariser avec les tableaux.


--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
Olivier Thomann
for (int i = 0; i < matrice.length; i++) {
for (int j = 0; j < matrice[i].length; j++) {
Il vaut mieux mettre la taille du tableau dans une variable locale pour

des raisons de performance.
for (int i = 0, length = matrice.length; i < length; i++) {
for (int j = 0, length2 = matrice[i].length; j < length2; j++) {

Mais bon avec les JITs peut-etre que tout cela ne fait pas de difference
en bout de ligne.
--
Olivier

Avatar
Sylvain
Olivier Thomann wrote on 10/05/2006 04:17:
for (int i = 0; i < matrice.length; i++) {
for (int j = 0; j < matrice[i].length; j++) {
Il vaut mieux mettre la taille du tableau dans une variable locale pour

des raisons de performance.
for (int i = 0, length = matrice.length; i < length; i++) {
for (int j = 0, length2 = matrice[i].length; j < length2; j++) {



c'est vrai ... mais pourquoi s'arréter en chemin ?

- une dimension d'un tableau statique est constante pour toute
sous-dimension, donc le nombre de colonnes (pour faire clair) est ici
constant pour toutes les lignes,
- un opérateur post-incrémental stocke la valeur courante, réalise
l'incrémentation, récupère la valeur ex-courante, or ici la valeur
courante de l'instruction de fin de boucle ne nous intéresse pas.

il vient:
int nbLines = matrice.length;
int nbRows = matrice[0].length;
for (int i = 0; i < nbLines; ++i)
for (int j = 0; j < nbRows; ++j)
matrice[i][j] = bState;

Sylvain.


Avatar
Hervé AGNOUX
Sylvain wrote:


il vient:
int nbLines = matrice.length;
int nbRows = matrice[0].length;
for (int i = 0; i < nbLines; ++i)
for (int j = 0; j < nbRows; ++j)
matrice[i][j] = bState;



Ahlàlàlàlàlàlà, tout çà ce sont des optimisations pour 2 chevaux ! Vous
initialisez 36 fois des variables à la même valeur ! Et la méthode clone
alors ?! Elle existe aussi pour les tableaux, il me semble !

Il vient :

public static void main(String[] args) throws Exception
{
boolean[][] matrice;
boolean[] col0;
int nbLines;
int nbRows;

nbLines = 7;
nbRows = 5;
matrice = new boolean[nbLines][nbRows];
col0 = new boolean[5];
for (int row = 0; row < nbRows; ++row)
col0[row] = false;
matrice[0] = col0;
for (int line = 1; line < nbLines; ++line)
matrice[line] = (boolean[])col0.clone();
// juste pour prouver : (mais ne prouve qu'à moitié)
System.out.println("matrice="+Arrays.asList(matrice));
}

Je remplis avec des for le premier rang, puis, pour les suivants, je clone
simplement ce premier rang.

(à ne pas faire avec des tableaux d'objets, hein).


--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
Stéphane Gibout
OK si c'est un tableau contenant des objets mais ici on a affaire à un
type <<de base>> (boolean). Je ne suis pas certain que l'utilisation du
clone soit beaucoup plus rapide. En tous cas, elle est beaucoup moins
claire...

Par contre déclarer les dimensions dans des variables globales (i.e.
hors de toute méthode) serait une bonne idée...
Avatar
Pierre Maurette

Merci à tous pour vos réponses. Je vois avec plaisir que Java est un
vrai langage et que les mouches auront intérêt à serrer les miches,
risquant la sodomie sur les petits détails ;-)

Finalement, comme j'avais:

private static final int LARGEUR_MATRICE = 5;
private static final int HAUTEUR_MATRICE = 7;

j'ai fait:

for (int i = 0; i < HAUTEUR_MATRICE; i++) {
for (int j = 0; j < LARGEUR_MATRICE; j++) {
dotMatrice_[i][j] = false;
}

(attention les mouches) J'en profite pour une petite question. Pour
avoir du code plus joli, en l'absence de préprocesseur, je fais:

private static final boolean LED_ON = true;
private static final boolean LED_OFF = false;

Est-ce correct ? Le remplacement a-t-il bien lieu à la compilation et
ainsi ne grève pas l'exécution ?

Y a-t-il une solution pour définir ce type de constantes au niveau de
l'application, du package en fait ?

Bonne journée à tous

--
Pierre Maurette
Avatar
Sylvain
Hervé AGNOUX wrote on 10/05/2006 08:33:

Ahlàlàlàlàlàlà, tout çà ce sont des optimisations pour 2 chevaux ! Vous
initialisez 36 fois des variables à la même valeur ! Et la méthode clone
alors ?! Elle existe aussi pour les tableaux, il me semble !

et il me semble, de plus, qu'un tableau est une classe en soi, et ce

quelle que soit sa dimension, donc tu pouvais écrire:

static final int LINES = 7;
static final int ROWS = 5;

boolean[][] matrice = new boolean[LINES][ROWS];
// ...
boolean[][] clone = (boolean[][]) matrice.clone();

c'est plus économique que les nbRows affectations et nbLines clone() ;-)

public static void main(String[] args) throws Exception
{
int nbLines = 7;
int nbRows = 5;
boolean[][] matrice = new boolean[nbLines][nbRows];
boolean[] col0 = new boolean[5];


(c'est pas du C K&R, il est plus propre de déclarer et d'initialiser)

for (int row = 0; row < nbRows; ++row)
col0[row] = false;


le point est qu'ici cela ne sert à rien, tout type primitif est
initialisé à 0/0.0/false; une méthode clone n'a de sens que pour
dupliquer l'état de la matrice après opérations ou pour l'initialiser
entièrement à true.

matrice[0] = col0;
for (int line = 1; line < nbLines; ++line)
matrice[line] = (boolean[])col0.clone();
}

(à ne pas faire avec des tableaux d'objets, hein).


oui d'aileurs, comment, en Java classique, surcharger la fonction membre
clone d'une ""classe tableau"" ?

Sylvain.

Avatar
Sylvain
Pierre Maurette wrote on 10/05/2006 10:38:

(attention les mouches) J'en profite pour une petite question. Pour
avoir du code plus joli, en l'absence de préprocesseur, je fais:

private static final boolean LED_ON = true;
private static final boolean LED_OFF = false;

Est-ce correct ? Le remplacement a-t-il bien lieu à la compilation et
ainsi ne grève pas l'exécution ?


c'est censé être 'remplacé' à la compil. (et les LED_XX disparaitrent
car private; mais ce sera sureemnt faux en debug).

Y a-t-il une solution pour définir ce type de constantes au niveau de
l'application, du package en fait ?


pas clair!

la classe 'LettreLed' (ou approchant) fait parti d'un package (même par
défaut) et ces constantes sont définies dans une classe (il ne peut
exister contrairement au C de data globales en Java).

si votre point est, est-il élégant de partager ces constantes à toutes
les classes du package de cette application (le famous com.pm.led
package), la réponse n'est que dans votre code, si vous les utilisez
dans différentes classes, définissez en effet un classe finale qui
définit toutes les constantes en package visible et utilisez-les avec
une qualification className.constanteName, ou encore définissez une
interface avec ces constantes (et sans méthodes) et (prétendez)
implémenter cette interface dans les classes pour utiliser une
qualification constanteName seule.

Sylvain.

Avatar
Pierre Maurette
Pierre Maurette wrote on 10/05/2006 10:38:
[...]

private static final boolean LED_ON = true;
private static final boolean LED_OFF = false;
[...]


si votre point est, est-il élégant de partager ces constantes à toutes les
classes du package de cette application (le famous com.pm.led package), la
réponse n'est que dans votre code, si vous les utilisez dans différentes
classes, définissez en effet un classe finale qui définit toutes les
constantes en package visible et utilisez-les avec une qualification
className.constanteName, ou encore définissez une interface avec ces
constantes (et sans méthodes) et (prétendez) implémenter cette interface dans
les classes pour utiliser une qualification constanteName seule.
Mon dieu mais c'est bien sûr ! C'est bien, l'interface. Avec

l'interface je définit LED_ON, avec une simple classe je définit ON,
puisque je l'appelle par className.ON

Merci.

--
Pierre Maurette


1 2