Hashmap -> uma lista por cada key

lenric

Power Member
Boas, estou há uns dias a olhar para isto sem saber bem como resolver.
Então é assim, tenho uma arraylist de Strings tipo a seguinte:

"bmw,bm,1990,3-series,40000"
"bmw,bm,2000,5-series,50000"
"mercedes,mb,1995,c-class,40000"
"mercedes,mb,2015,a-class,30000"
"mercedes,mb,2020,b-class,35000"
"toyota,toy,2015,auris,25000"

Ou seja, cada espaço da arraylist corresponde a cada linha.

Tenho a classe Brand (argumentos das posições 0 e 1 de cada linha, feito o split(",")), e a model(argumentos são as restantes posições).

Quero criar uma LinkedHashMap assim: Map<Brand, List<Model>> m = new LinkedHashMap< > ()

Ou seja, por cada key (brand) tenho um value (uma lista de models).

Como fazer isto? (se a hashmap não tivesse como 2º parâmetro uma list eu saberia fazer)

Obrigado
 
Assumindo que a tua ArrayList de string está sempre ordenada de forma alfabética, consegui o resultado fazendo o seguinte:

Código:
Map<String, List<String>> m = new LinkedHashMap<> ();
LinkedList<String> brandModels = new LinkedList<>();
String previousBrand = "";

ArrayList<String> cars = new ArrayList<String>();
cars.add("bmw,bm,1990,3-series,40000");
cars.add("bmw,bm,2000,5-series,50000");
cars.add("mercedes,mb,1995,c-class,40000");
cars.add("mercedes,mb,2015,a-class,30000");
cars.add("mercedes,mb,2020,b-class,35000");
cars.add("toyota,toy,2015,auris,25000");

for(int i = 0; i < cars.size(); i++) {

    // Divide a string em várias partes e associa a uma variável
    String[] parts = cars.get(i).split(",");
    String brand = parts[0];
    String shortName = parts[1];
    String year = parts[2];
    String model = parts[3];
    String kms = parts[4];

    // Se for o primeiro valor do array
    if(i == 0) previousBrand = brand;

    if(!previousBrand.equals(brand)) {
        previousBrand = brand;
        brandModels = new LinkedList<>();
        brandModels.add(model);
    } else {
        brandModels.add(model);
    }

    // Insere no LinkedHashMap
    m.put(brand, brandModels);
}
System.out.println(m);

Estão aí algumas más práticas muito provavelmente, mas fez o trabalho (acho eu) :D

PS: O output foi o seguinte:
{bmw=[3-series, 5-series], mercedes=[c-class, a-class, b-class], toyota=[auris]}
 
Última edição:
Assumindo que a tua ArrayList de string está sempre ordenada de forma alfabética, consegui o resultado fazendo o seguinte:

Código:
Map<String, List<String>> m = new LinkedHashMap<> ();
LinkedList<String> brandModels = new LinkedList<>();
String previousBrand = "";

ArrayList<String> cars = new ArrayList<String>();
cars.add("bmw,bm,1990,3-series,40000");
cars.add("bmw,bm,2000,5-series,50000");
cars.add("mercedes,mb,1995,c-class,40000");
cars.add("mercedes,mb,2015,a-class,30000");
cars.add("mercedes,mb,2020,b-class,35000");
cars.add("toyota,toy,2015,auris,25000");

for(int i = 0; i < cars.size(); i++) {

    // Divide a string em várias partes e associa a uma variável
    String[] parts = cars.get(i).split(",");
    String brand = parts[0];
    String shortName = parts[1];
    String year = parts[2];
    String model = parts[3];
    String kms = parts[4];

    // Se for o primeiro valor do array
    if(i == 0) previousBrand = brand;

    // Se não for nem o primeiro nem último valor do array
    if(!previousBrand.equals(brand)) {
        previousBrand = brand;
        brandModels = new LinkedList<>();
        brandModels.add(model);
    } else {
        brandModels.add(model);
    }

    // Insere no LinkedHashMap
    m.put(brand, brandModels);
}
System.out.println(m);

Estão aí algumas más práticas muito provavelmente, mas fez o trabalho (acho eu) :D

PS: O output foi o seguinte:
{bmw=[3-series, 5-series], mercedes=[c-class, a-class, b-class], toyota=[auris]}

O que eu vou dizer pode não estar certo porque não testei nada, mas acho que estás a complicar ao usar uma LinkedList.

O que se pode fazer é separar a marca para uma variável, como tu fizeste, e usar isso como a key do mapa. Para o value do mapa pode-se ter uma lista de um objecto chamado Model, que recebe no construtor as outras variáveis. Ou seja, fica algo assim:

Código:
Map<String, List<Model>> m = new LinkedHashMap<> ();

ArrayList<String> cars = new ArrayList<String>();
cars.add("bmw,bm,1990,3-series,40000");
cars.add("bmw,bm,2000,5-series,50000");
cars.add("mercedes,mb,1995,c-class,40000");
cars.add("mercedes,mb,2015,a-class,30000");
cars.add("mercedes,mb,2020,b-class,35000");
cars.add("toyota,toy,2015,auris,25000");

for(int i = 0; i < cars.size(); i++) {

    // Divide a string em várias partes e associa a uma variável
    String[] parts = cars.get(i).split(",");
    String brand = parts[0];
    String shortName = parts[1];
    String year = parts[2];
    String model = parts[3];
    String kms = parts[4];

    Model model = new Model(shortName, year, model, kms);
    List<Model> models = Arrays.asList(model);

    // Insere no LinkedHashMap
    m.put(brand, models); 
}
System.out.println(m);

Acho que ficaria algo assim, mas não testei nada de nada. Fica mais simplificado, apesar de se ter de criar uma classe extra.
 
Assumindo que a tua ArrayList de string está sempre ordenada de forma alfabética, consegui o resultado fazendo o seguinte:

Código:
Map<String, List<String>> m = new LinkedHashMap<> ();
LinkedList<String> brandModels = new LinkedList<>();
String previousBrand = "";

ArrayList<String> cars = new ArrayList<String>();
cars.add("bmw,bm,1990,3-series,40000");
cars.add("bmw,bm,2000,5-series,50000");
cars.add("mercedes,mb,1995,c-class,40000");
cars.add("mercedes,mb,2015,a-class,30000");
cars.add("mercedes,mb,2020,b-class,35000");
cars.add("toyota,toy,2015,auris,25000");

for(int i = 0; i < cars.size(); i++) {

    // Divide a string em várias partes e associa a uma variável
    String[] parts = cars.get(i).split(",");
    String brand = parts[0];
    String shortName = parts[1];
    String year = parts[2];
    String model = parts[3];
    String kms = parts[4];

    // Se for o primeiro valor do array
    if(i == 0) previousBrand = brand;

    if(!previousBrand.equals(brand)) {
        previousBrand = brand;
        brandModels = new LinkedList<>();
        brandModels.add(model);
    } else {
        brandModels.add(model);
    }

    // Insere no LinkedHashMap
    m.put(brand, brandModels);
}
System.out.println(m);

Estão aí algumas más práticas muito provavelmente, mas fez o trabalho (acho eu) :D

PS: O output foi o seguinte:
{bmw=[3-series, 5-series], mercedes=[c-class, a-class, b-class], toyota=[auris]}


Obrigado!

Vou tentar transformar esta solução para ter como parâmetros objetos.
Eu inicialmente tinha passado tudo para um linkedhashmap e, depois, passava para outro usando o containsKey() para ter Brand, List<Model>, mas, por mais que tentasse, não estava a fazer a mínima ideia de como o fazer.
 
Se quiseres mesmo usar um HashMap sugeria alterares a classe Brand para que aceitasse como propriedade:
string nickName;
List<string> models;

e a HashMap seria Map<string, Brand>

<code>
foreach(var item in arrayList)
{
var arrayTemp = item.Split(",");
//validar sempre se o array tem valores, etc

List<string> models = new List<string> ();

for(int i = 2; i < cars.size(); i++)
{
models.Add( arrayTemp[pos i] );
}

Brand brand = map.Get(array[0]);
if(brand == null)
{
brand = new Brand();
brand.Name = arrayTemp[0];
brand.NickName = arrayTemp[1];
brand.models = models;
map.Add(brand.Name, brand);
} else
{
brand.models.AddRange(models);
}


}
<code>


Assim de cabeça parece-me isto.

Edit: dei mais um jeitinho nisso.
 
Última edição:
Se quiseres mesmo usar um HashMap sugeria alterares a classe Brand para que aceitasse como propriedade:
string nickName;
List<string> models;

e a HashMap seria Map<string, Brand>

<code>
foreach(var item in arrayList)
{
var arrayTemp = item.Split(",");
//validar sempre se o array tem valores, etc

List<string> models = new List<string> ();

for(int i = 2; i < cars.size(); i++)
{
models.Add( arrayTemp[pos i] );
}

Brand brand = map.Get(array[0]);
if(brand == null)
{
brand = new Brand();
brand.Name = arrayTemp[0];
brand.NickName = arrayTemp[1];
brand.models = models;
map.Add(brand.Name, brand);
} else
{
brand.models = models;
}


}
<code>


Assim de cabeça parece-me isto.

Edit: dei mais um jeitinho nisso.


O HashMap dá-me jeito, porque depois vou ter de o usar para outras alíneas, além de ser "exigido".
Obrigado!
 
Back
Topo