Meter un Set en un Map

Iniciado por kikian94, 27 Febrero 2015, 14:43 PM

0 Miembros y 1 Visitante están viendo este tema.

kikian94

Hola, necesito crear un almacen de provincias, las cuales a su vez tienen poblaciones asociadas, tiene que hacerse con un map en el que la clave es el nombre de la provincia y el valor un set con las poblaciones, hasta ahi todo bien, el problema lo tengo en añadir las poblaciones al set que no se como hacerlo ya que tengo que pasar por el map antes, tengo esta clase:
Código (java) [Seleccionar]


Map<String, Set<Poblacion>> Aprovincias = new HashMap<String, Set<Poblacion>>();

public boolean addPoblacion(String provincia, IPoblacion poblacion) {
boolean res = false;
if(!!Aprovincias.containsValue(provincia)){
res = false;
System.out.println("La Provincia no existe, creela antes de añadir poblacion");
}else{

//Aprovincias.put(provincia, );
                        Aqui es donde tengo el problema, ya que no se que hacer
}
return res;
}



Usuario Invitado

#1
Dado que una Map trabaja con objetos, puedes en primer lugar agregar al mapa solo las provincias e inicializar sus poblaciones con null:

Código (java) [Seleccionar]
private void fillProvinces(String... provincesNames) {
for(String provinceName : provincesNames)
provinces.add(provinceName, null);
}


Luego procedemos a agregar las poblaciones a las provincias. Si el Mapa no contiene la provincia, retorna false. Pero si contiene la provincia, realizamos algunos pasos:

  • Obtener la población asociada a dicha provincia.

    Ésto nos permite hacer dos cosas:

  • Si devuelve null, quiere decir que no hay población para dicha provincia y procedemos a crear un nuevo HashSet, agregamos los valores al HashSet población y lo agregamos al Map.

  • Si no devuelve null, quiere decir que ya existe población y entonces, obtenemos la población de la provincia y le agregamos más poblaciones, en lugar de crear otra porque sobre-escribiría el antiguo HashSet.

    Código (java) [Seleccionar]
    public boolean addPopulationToProvince(String provinceName, IPopulation population) {
    boolean success = false;
    if(!provinces.containsValue(provinceName)) {
    System.out.println("La provincia no existe, créela antes de añadir la polación");
                   return success;
    }
    if(provinces.get(provinceName) == null) {
    Set<IPopulation> population = new HashSet<>();
           population.add(population);
            provinces.add(provinceName, population);
                   success = true;
    } else {
    Set<IPopulation> population = getPopulationFromProvince(provinceName);
    population.add(population);
                   success = true;
    }
           return success;
    }


    Éste método devuelve el HashSet población asociado a dicha provincia para poder agregarle elementos:

    Código (java) [Seleccionar]
    private Set<IPopulation> getPopulationFromProvince(String provinceName) {
    Set<IPopulation> population = null;
    for(Map.Entry<String, Set<IPopulation> entry : provinces.entrySet()) {
    if(entry.getKey().equals(provinceName))
    population = entry.getValue();
    }
    return population;
    }


    Un saludo.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

kikian94

hola, gracias por contestar, la primera parte del codigo la entiendo perfectamente, pero la segunda no, no se utilizar el entrySet para agregar provincias al Set y luego meter el Set en el Map

Usuario Invitado

Te explico. Map.Entry simula una entrada de un Map, en este caso del Map provinces. El método entrySet() lo que haces es deolver un set con pares tipo Entry. Entonces, cuál es la entrada del Map provinces? Llave: String, Valor: HashSet, porque de esos valores está compuesto el Map provinces.

Ese método recibe como parámetro el nombre de la provincia. Recorre el mapa entrada por entrada y compara el nombre de la provincia actual que se esta recorriendo con el nombre de la provincia pasada por parámetro. Si coinciden se devuelve el HashSet que contiene laa poblaciones asociadas a dicha provincia.

La logica es sencilla:

1) Obtiene la poblacion de la provincia.
2) Si el HashSet asociado a dicha provincia es Null se crea un HashSet, se le asignan valores y se agrega al Map asociándose con la provincia.
3) Si el HashSet asociado a la provincia no es Null quiere decir que ya hay poblacion para dicha provincia, por lo que se recupera el HashSet y se le agrega otra poblacion.

Espero se haya entendido. Cualquier duda la comentas. Saludos.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

kikian94

#4
Cita de: Gus Garsaky en  2 Marzo 2015, 11:40 AM

vale, creo que ya lo he entendido, he codificado el metodo asi:


Código (java) [Seleccionar]
public boolean addPoblacion(String provincia, IPoblacion poblacion) {
boolean res = false;
if(!!Aprovincias.containsValue(provincia)){
res = false;
System.out.println("La Provincia no existe, creela antes de añadir poblacion");
}else{
SortedSet<IPoblacion> sPoblacion = (SortedSet<IPoblacion>) getPoblacion(provincia);
sPoblacion.add(poblacion);
Aprovincias.put(provincia, sPoblacion);
res = true;
}
return res;
}



pero al hacer un test del programa con este codigo:

Código (java) [Seleccionar]
public class test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

Map<String, Set<IPoblacion>> Aprovincias = new HashMap<String, Set<IPoblacion>>();

Poblacion poblacion = new Poblacion("Getafe",0,"Madrid");
Poblacion poblacion2 = new Poblacion("Leganes", 345,"Madrid");

AlmacenPoblaciones provincias = new AlmacenPoblaciones();
provincias.addProvincia("Madrid");
provincias.addPoblacion("Madrid", poblacion);
//provincias.addPoblacion("Madrid", poblacion2);
}

}


me da nullpointer exception en la linea en la que añado la poblacion al Set, el metodo que utilizo para sacar el set lo he codificado asi:
Código (java) [Seleccionar]
private Set<IPoblacion> getPoblacion(String provincia) {
Set<IPoblacion> poblacion = null;
for(Map.Entry<String, Set<IPoblacion>> entry : Aprovincias.entrySet()) {
if(entry.getKey().equals(provincia))
poblacion = entry.getValue();
}
return poblacion;
}


Creo que el error lo tengo en el tipo de objeto que meto en el Set, pero me hago un lio por que el set tiene objetos de tipo Ipoblacion que es una interfaz que tengo que implementar y lo que yo creo son poblaciones de la clase poblacion que es la clase que queda al implementarse Ipoblacion

[\quote]

Usuario Invitado

#5
Cuando te ocurra una excepción, ponle mucho detalle al rastreo de pila que te muestra. Allí hay mucha información acerca del problema, por eso te lo muestra.

Un NullPointerException es una excepción que ocurre cuando se trata de acceder a un valor null. El error que deduzco es que tu el método getPoblacion() no está devolviendo el set.

Los errores pueden ser 2:

1) Que no se haya agregado la provincia "Madrid".
2) Que por alguna razón no esté detectando a "Madrid" cuando se itera el mapa.

Te he hecho algo parecido para que lo tomes como referencia, por que no sé el contenido de "AlmacenPoblaciones".

Population (Población):

Código (java) [Seleccionar]
package net.elhacker.demo.model.entities;

public interface Population {

String getProvinceName();
   void setProvinceName(String provinceName);
   int getSomething();
   void setSomething(int value);
   String getStateName();
   void setStateName(String stateName);
   
}


PopulationImp (PoblacionImp):

Código (java) [Seleccionar]
package net.elhacker.demo.model.entities;

public class PopulationImp implements Population {

private String provinceName;
private int something;
private String stateName;

public PopulationImp() {}

public PopulationImp(String provinceName, int something, String stateName) {
super();
this.provinceName = provinceName;
this.something = something;
this.stateName = stateName;
}

@Override
public String getProvinceName() {
return provinceName;
}

@Override
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}

@Override
public int getSomething() {
return something;
}

@Override
public void setSomething(int something) {
this.something = something;
}

@Override
public String getStateName() {
return stateName;
}

@Override
public void setStateName(String stateName) {
this.stateName = stateName;
}


}


PopulationService (Servicio de población). Esto vendría a ser tu "AlmacenPoblaciones":

Código (java) [Seleccionar]
package net.elhacker.demo.model.services;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import net.elhacker.demo.model.entities.Population;

public class PopulationService {

private static Map<String, Set<Population>> provincesAndPopulations;

public PopulationService() {
provincesAndPopulations = new HashMap<>();
}

public void addProvince(String provinceName) {
if(provincesAndPopulations.containsKey(provinceName)) return;
provincesAndPopulations.put(provinceName, null);
}

public Object[] addPopulation(String provinceName, Population population) {
Object[] response = new Object[2];
if(!provincesAndPopulations.containsKey(provinceName)) {
response[0] = "La provincia no existe, primero créela";
response[1] = false;
} else {
Set<Population> provincePopulation = this.getPopulationByProvinceName(provinceName);
provincePopulation.add(population);
response[0] = "Provincia añadida correctamente";
response[1] = true;
}
return response;
}

public boolean addProvinceAndPopulation(String provinceName, Population population) {
boolean success = false;
if(!provincesAndPopulations.containsKey(provinceName)) {
Set<Population> provincePopulation = new HashSet<>();
provincePopulation.add(population);
provincesAndPopulations.put(provinceName, provincePopulation);
success = true;
}
return success;
}

private Set<Population> getPopulationByProvinceName(String provinceName) {
Set<Population> population = null;
for(Map.Entry<String, Set<Population>> entry : provincesAndPopulations.entrySet()) {
if(entry.getKey().equals(provinceName))
population = entry.getValue();
}
return population;
}

public void showAll() {
for(Map.Entry<String, Set<Population>> entry : provincesAndPopulations.entrySet()) {
System.out.println("Poblaciones del estado "+entry.getKey()+":\n");
for(Population population : entry.getValue()) {
System.out.println(population.getProvinceName());
System.out.println(population.getSomething());
System.out.println(population.getStateName());
System.out.println();
}
System.out.println();
}
}


}


Test (main):

Código (java) [Seleccionar]
package net.elhacker.demo;

import net.elhacker.demo.model.entities.Population;
import net.elhacker.demo.model.entities.PopulationImp;
import net.elhacker.demo.model.services.PopulationService;

public class Test {

public static void main(String[] args) {
PopulationService populationService = new PopulationService();
Population population = new PopulationImp("Getafe", 0, "Madrid");
populationService.addProvinceAndPopulation("Madrid", population);
population = new PopulationImp("Leganes", 345, "Madrid");
Object[] response = populationService.addPopulation("Madrid", population);
System.out.println(response[0]);

System.out.println("\n*** Mostrando todas las provincias y sus poblaciones ***\n");
populationService.showAll();

}

}


Resultado de la ejecución:

CitarProvincia añadida correctamente

*** Mostrando todas las provincias y sus poblaciones ***

Poblaciones del estado Madrid:

Getafe
0
Madrid

Leganes
345
Madrid

PD: NO uses doble negación!.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

kikian94

La doble negacion se me ha pasado, lo ejecuto todo pero me dice que no puedo añadir la poblacion por que la provincia no existe, y me da otra vez nullpointerexception

Código (java) [Seleccionar]
public class AlmacenPoblaciones implements IAlmacenPoblaciones {

Map<String, SortedSet<IPoblacion>> Aprovincias = new HashMap<String, SortedSet<IPoblacion>>();


private SortedSet<IPoblacion> getPoblacion(String provincia) {
SortedSet<IPoblacion> poblacion = null;
for(Map.Entry<String, SortedSet<IPoblacion>> entry : Aprovincias.entrySet()) {
if(entry.getKey().equals(provincia))
poblacion = entry.getValue();
}
return poblacion;
}

@Override
public boolean addPoblacion(String provincia, IPoblacion poblacion) {
boolean res = false;
if(!Aprovincias.containsKey(provincia)){
res = false;
System.out.println("La Provincia no existe, creela antes de añadir poblacion");
}else{
SortedSet<IPoblacion> sPoblacion = getPoblacion(provincia);
sPoblacion.add(poblacion);                   Aqui es donde me da error y no se por que
Aprovincias.put(provincia, sPoblacion);    Aqui es donde me da error y no se por que
res = true;
}
return res;
}


@Override
public boolean addProvincia(String provincia) {
SortedSet<IPoblacion> poblaciones = null;
boolean res = false;
if(Aprovincias.containsKey(provincia)){
System.out.println("Ya existe la provincia");
}else{
Aprovincias.put(provincia, poblaciones);
res = true;
}
return res;
}

@Override
public boolean containsPoblacion(String provincia, String poblacion) {

boolean res = false;
if(!!Aprovincias.containsValue(provincia)){
res = false;
System.out.println("La Provincia no existe, creela antes de eliminar poblacion");
}else{
SortedSet<IPoblacion> sPoblacion = (SortedSet<IPoblacion>) getPoblacion(provincia);
if(sPoblacion.contains(poblacion)){
res = true;
}

}
return res;

}

@Override
public boolean containsPoblacion(String arg0, IPoblacion arg1) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean containsProvincia(String provincia) {
boolean res = false;
if(Aprovincias.containsKey(provincia)){
res = true;
System.out.println("La provincia esta en el almacen");
}else{
System.out.println("La provincia no esta en el almacen");
}
return res;
}



mi metodo main es este

Código (java) [Seleccionar]
public class test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stu

Poblacion poblacion = new Poblacion("Getafe",0,"Madrid");
Poblacion poblacion2 = new Poblacion("Leganes", 345,"Madrid");

AlmacenPoblaciones provincias = new AlmacenPoblaciones();
provincias.addProvincia("Madrid");
provincias.addPoblacion("Madrid", poblacion);
provincias.addPoblacion("Madrid", poblacion2);

}

}



y la clase poblacion es tal cual tu me la has escrito mas arriba, puede estar el error en el tipo de objeto que añado? ya que la clase es poblacion y el set tiene ipoblacion

Usuario Invitado

Veo un error aquí:

Código (java) [Seleccionar]
if(!!Aprovincias.containsValue(provincia)){
   res = false;

   System.out.println("La Provincia no existe, creela antes de eliminar poblacion");

}


Analiza lo siguiente:

Código (java) [Seleccionar]
!Aprovincias.containsValue(provincia)

Si "Madrid" ya está en el Map esto devuelve false. Pero al negar esa condición con nuevamente como estás haciendo:

Código (java) [Seleccionar]
!!Aprovincias.containsValue(provincia)

Ese false se vuelve true y por eso te imprime el mensaje "La provincia no existe".




1) ¿Cuándo añades la provincia solamente:

Código (java) [Seleccionar]
public boolean addProvincia(String provincia) {

34. boolean res = false;

35. if(Aprovincias.containsKey(provincia)){

36. System.out.println("Ya existe la provincia");

37. }else{

38. Aprovincias.put(provincia, null);

39. res = true;

40. }

41. return res;

42. }



¿Devuelve true? Has tests en lugar de adivinar.

Código (java) [Seleccionar]
boolean response = provincias.addProvincia("Madrid");
System.out.println(response);


Respecto a tu pregunta, la respuesta es NO. Cuando una clase implementa una interface, ésta clase automáticamente se convierte en el mismo tipo de la interfaz. Si tu haces:

Código (java) [Seleccionar]
Población instanceof IPoblacion

Devolverá true, ya que Población al implementar IPoblacion, automáticamente se convierte en tipo de ésta interface.

Es por eso que es posible hacer:

Código (java) [Seleccionar]
List<String> lista = new ArrayList<>();

List es una interface y ArrayList es una clase que implementa a List.




Recapitulando:

  • Haz el test anteriormente dicho.

    ¿Has probado mi clase? No tiene ningún error. Trata de compararlas e identificar errores.

    En tu próxima respuesta:

  • Pega el rastreo de pila (El texto rojo que indica el NullPointerException).


    Salu2.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

kikian94

ya he solucionado el problema, estaba en que cuando creaba la provincia creaba un set con valor null y yo pensaba que al poner null era que estaba vacio, ahi tenia el error, ahora solo me queda codificar 3 clases mas, una para guardar en fichero, otra para escribir y otra para ordenar por habitantes o nombre

Código (java) [Seleccionar]
public boolean guardar(String escritura) {
try{
File fichero = new File (escritura);
FileWriter escribir = new FileWriter (fichero);
for(Map.Entry<String,SortedSet<IPoblacion>> entry: Aprovincias.entrySet()){
escribir.write(entry.getKey() + " " +  entry.getValue());
}
escribir.close();
return true;
}catch(Exception e){
e.printStackTrace();
}
return false;
}

@Override
public boolean ordenarPor(String provincia, int ordenarPor) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean recuperar(String arg0) {
// TODO Auto-generated method stub
return false;
}



al escribir el fichero me dice esto
Código (java) [Seleccionar]
java.io.FileNotFoundException: c:\prueba.txt (Acceso denegado)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileWriter.<init>(Unknown Source)
at AlmacenPoblaciones.guardar(AlmacenPoblaciones.java:276)
at test.main(test.java:26)



kikian94

#9
vale, perdon por la tonteria, el problema era la raiz del disco c, ahora si me deja...., solo me queda el metodo que ordena y el de leer