Dans un chapitre du premier cours sur Java, vous avez découvert les tableaux. Nous allons nous intéresser à d'autres outils permettant de stocker plusieurs valeurs, des outils plus polyvalents !
Arraylist
Commençons par un petit rappel sur les tableaux et sur leurs limites.
jshell> int[] ages = new int[10]; ages ==> int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } jshell> ages[9] = 5; $26 ==> 5 jshell> ages[10] = 16; | java.lang.ArrayIndexOutOfBoundsException thrown: 10 | at (#27:1) jshell> for (int i = 0; i < 10; i++) { ...> if (ages[i] == 17) { ...> System.out.println("17 ans !"); ...> } ...> }
L'inconvénient majeur des tableaux est leur taille prédéfinie.
Deuxième inconvénient : dès lors que l'on veut un comportement avancé, il faut forcément le coder. Il n'y aucune fonctionnalité livrée avec les tableaux.
Les nouveaux types que nous allons voir dans ce chapitre sont des types objets. Ils contiennent donc énormément de fonctionnalités !
Regardons la javadoc d'Arraylist. La partie Method Summary contient les fonctionnalités disponibles. Nous voyons par exemple que l'on peut :
ajouter une nouvelle valeur avec
add
;savoir si la liste contient une valeur avec
contains
;supprimer une valeur avec
remove
.
Voici un exemple d'utilisation :
jshell> List<String> names = new ArrayList<String>(); names ==> [] jshell> names.add("Romain"); $34 ==> true jshell> names.add("Julie"); $35 ==> true jshell> names.add("Sylvain"); $36 ==> true jshell> names; names ==> [Romain, Julie, Sylvain] jshell> names.contains("Julie"); $38 ==> true jshell> names.remove("Romain"); $39 ==> true jshell> names names ==> [Julie, Sylvain] jshell> names.get(1); $41 ==> "Sylvain" jshell> names.indexOf("Julie"); $42 ==> 0
Il est possible de faire énormément de choses avec des ArrayList
!
Que veux dire <String> ?
Certaines classes peuvent fonctionner avec différents types. Un ArrayList
peut stocker des String
, mais aussi des Integer
, des Double
ou pourquoi pas des Scanner
! Cela s'appelle des types génériques.
Pourquoi names
est de type List<String>
et pas ArrayList<String>
?
Pour comprendre cette notion, il faut comprendre l'héritage et le polymorphisme. Plusieurs chapitres sont dédiés à ce sujet dans la suite du cours.
HashMap
Pour connaître les HashMap
, commencez par regarder la javadoc. Pour résumer simplement, une HashMap
sert à stocker des couples clé/valeur. Nous allons utiliser cet outil dans la classe Bill
.
Utilisons HashMap
dans Jshell :
jshell> Map<String, Integer> ages = new HashMap<String, Integer>(); ages ==> {} jshell> ages.put("Sarah", 22); $44 ==> null jshell> ages ages ==> {Sarah=22} jshell> ages.put("Paul", 31); $46 ==> null jshell> ages.put("Melissa", 45); $47 ==> null jshell> ages ages ==> {Melissa=45, Sarah=22, Paul=31} jshell> ages.put("Sarah", 23); $49 ==> 22 jshell> ages ages ==> {Melissa=45, Sarah=23, Paul=31} jshell> ages.containsKey("Paul"); $52 ==> true jshell> ages.get("Paul"); $51 ==> 31 jshell> ages.remove("Melissa"); $53 ==> 45 jshell> ages ages ==> {Sarah=23, Paul=31}
Je pense que vous avez compris le comportement d'une HashMap
. Pour chaque clé, nous avons une valeur unique. Si nous ajoutons une nouvelle valeur pour une clé qui existe déjà, la valeur précédente est remplacée.
On passe à la facture !
Cette fois-ci, je vous donne l'UML de Bill
. Vous êtes normalement capable de créer la classe.

Et le code :
package com.cursan.homeshop;
import java.util.Map;
public class Bill {
private Customer customer;
private Map<Product, Integer> products;
/**
* Add a product with a quantity in the bill
* @param product product to add
* @param quantity quantity of the product
*/
public void addProduct(Product product, Integer quantity) {
this.products.put(product, quantity);
}
public Customer getCustomer() {
return customer;
}
public Map<Product, Integer> getProducts() {
return products;
}
}
Pourquoi utilise-t-on Integer
ici et pas int
?
À chaque type primitif correspond un type objet :
int
->Integer
double
->Double
boolean
->Boolean
Ces types objets permettent d'avoir plus de fonctionnalités que les types primitifs. Dans certains cas, vous êtes obligé d'en utiliser. Une Map
ne peut pas travailler avec des objets primitifs, mais seulement avec des objets.
Pour savoir quand utiliser l'un ou l'autre, c'est simple : utilisez au maximum les types primitifs. Si vous avez besoin de fonctionnalités avancées ou si vous n'avez pas le choix, utilisez les types objets.
Les constructeurs
Vous avez peut-être remarqué quelque chose. Si customer
n'est accessible que via un getter, comment lui donner une valeur ?
Avec les types objets, il y a une notion importante appelée constructeur. Un constructeur, comme son nom l'indique, permet de construire un objet.
jshell> String texte = new String("ceci est un texte"); texte ==> "ceci est un texte"
Vous le voyez ici, quand on crée une variable de type String
: on peut lui passer un paramètre, comme avec une méthode. En faisant cela, c'est le constructeur de String
qui est utilisé.
Voici un constructeur pour Bill
:
public Bill(Customer customer) {
this.customer = customer;
}
C'est une méthode sans valeur de retour, qui porte le même nom que sa classe. Il peut très bien y avoir plusieurs constructeurs pour une classe. String
, par exemple, peut être construit avec ou sans chaîne de caractères.
L'UML permet aussi de visualiser les constructeurs :

Voici les UML de Customer
et de Product
avec leur constructeur.


Le code associé :
package com.cursan.homeshop;
public class Customer {
private String fullname;
private String address;
public Customer(String fullname, String address) {
this.fullname = fullname;
this.address = address;
}
public String getFullname() {
return fullname;
}
public String getAddress() {
return address;
}
}
package com.cursan.homeshop;
public class Product {
private String name;
private String description;
private double price;
public Product(String name, String description, double price) {
this.name = name;
this.description = description;
this.price = price;
}
/**
* Display a full description of the product
*/
public void look() {
System.out.println(String.format(name + " : " + price + "%n" + description));
}
/**
* Add the product to a Bill
*/
public void buy(Bill bill, Integer quantity) {
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
Nous venons de terminer cette partie. Nous avons commencé à découvrir :
la programmation orientée objet en Java
la modélisation via les diagrammes de classes UML
les visibilités
les collections
Dans la prochaine partie, nous irons plus loin avec ces nouveaux concepts et découvrirons des notions avancées de la programmation orientée objet comme l'héritage, le polymorphisme et les interfaces !