Java - Estoy estancado, una ayuda por favor

 
Vista:
sin imagen de perfil
Val: 23
Ha disminuido 1 puesto en Java (en relación al último mes)
Gráfica de Java

Estoy estancado, una ayuda por favor

Publicado por Joel (9 intervenciones) el 01/09/2019 21:45:52
Buenas, estoy aprendiendo lo que es la programación orientada a objetos, y estaba resolviendo este ejercicio de una tienda, solo que me quedé estancado no encuentro la manera de completar estos métodos, toda ayuda se agradece y es bienvenida, a continuación les dejo mi proyecto.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Kabuto
Val: 1.754
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Estoy estancado, una ayuda por favor

Publicado por Kabuto (436 intervenciones) el 02/09/2019 01:51:05
Cosas a corregir/completar.

Tienes dos métodos para agregar producto. Uno recibe un objeto Producto ya creado, lo agrega al arreglo y aumenta contador. OK

El otro en lugar de un Producto, recibe los datos necesarios para crear el Producto.
Bien, este método crea un Producto con dichos datos, pero no lo agrega a la Tienda.

1
2
3
public void agregarProducto(String nombre, String categoria, float precio) {
        Producto nuevo = new Producto(nombre,categoria,precio);
    }

Debería además de crear el Producto, agregarlo y aumentar el contador.
1
2
3
4
public void agregarProducto(String nombre, String categoria, float precio) {
    	lista[contador] = new Producto(nombre,categoria,precio);
        contador++;
    }

Dicho esto, ambos métodos carecen de una cosa importante. Los Productos se agregan sin primero comprobar si queda espacio para agregarlos.
Tu "Tienda" comienza con una lista de Productos con un tamaño limite. Antes de agregar productos, se debería comprobar si se ha alcanzado ese límite o no.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void agregarProducto(Producto p) {
    	if (contador < lista.length) {
    		lista[contador] = p;
    		contador++;
    	}
    	else
    		System.out.println("No queda espacio para más Productos");
    }
 
    public void agregarProducto(String nombre, String categoria, float precio) {
    	if (contador < lista.length) {
    		lista[contador] = new Producto(nombre,categoria,precio);
    		contador++;
    	}
    	else
    		System.out.println("No queda espacio para más Productos");
    }

Por cierto, usar un array simple es muy poco versátil. Desconozco cuáles son las condiciones del enunciado de tu ejercicio, pero a no ser que se esté especificando que se deben usar arrays simples, sería mucho mejor y más lógico usar colecciones dinámicas que no tienen tamaño límite y van creciendo/disminuyendo según se añaden/eliminan elementos, como puede ser la clase Vector o ArrayList, por mencionar algunas.
Usar array simple supone muchos inconvenientes, por ejemplo a la hora de "borrar" productos de la Lista, como veremos después.

Sigamos.
Tienes pendiente completar un método para mostrar un Producto buscando por el "nombre.
Esto tendrás que hacerlo con un bucle que recorra la lista de Productos, pero no debe recorrerla entera, solo hasta donde indique la variable "contador", ya que más allá de esta posición no habrán Productos que se puedan consultar.
Por cada elemento de la "lista" comparamos su nombre con el que nos han pasado como argumento.
Si coincide, se hace un return con los datos y esto pone fin al bucle que recorre la lista.
Si el bucle llega a su fin, sin que se haya retornado ninguna coincidencia, es que no existe Producto con ese nombre, y así lo informamos.

1
2
3
4
5
6
7
8
public String verProducto(String nombre) {
        for (int j = 0; j < contador; j++) {
        	if (lista[j].getNombre().equals(nombre)) //Producto encontrado, retornamos datos.
        		return lista[j].getNombre() + " -- " + lista[j].getPrecio();
        }
        //Si terminado el bucle for no se ha retornado nada, es que no existe este Producto
        return "No se ha encontrado Producto con el nombre: " + nombre;
    }

El siguiente método lo dejo como la has hecho tú, pero no es como yo lo haría.
Yo, igual que antes, recorrería solo hasta donde me diga "contador" y así evito tener que gestionar la posibilidad de encontrarme con posiciones que tengan valor null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public String verLista() {
        String texto = "";
        for (int j = 0; j < lista.length; j++) {
 
            Producto aux = lista[j];
            if (aux != null) {
                texto += aux.getInfo() + "\n";
 
            } else {
                texto += "-- vacio --\n";
            }
        }
        return texto;
    }

El siguiente:
1
2
3
4
public float getTotalProductos() {
        //Obtener total de poduto TAREA
        return 0;
    }

Puesto que retorna un float, supongo que hay que calcular la suma de todos los precios de Productos.
Esto es fácil, usamos un bucle hasta donde diga "contador" y hacemos la suma.
1
2
3
4
5
6
7
8
public float getTotalProductos() {
        float suma = 0;
 
        for (int j = 0; j < contador; j++)
        	suma += lista[j].getPrecio();
 
        return suma;
    }

Sigamos.
Método que devuelve el número de productos, es decir, cuantos productos hay...Pues nos basta con devolver lo que diga "contador".
1
2
3
public int getNroProductos() {
        return contador;
    }

Siguiente método, borrar producto indicándonos la posición que hay que borrar.
Aquí es donde nos encontramos con problemas por usar arrays simples.
Podríamos pensar que la solución fácil es dar valor null a la posición indicada, decrementamos la variable "contador" y ya damos por borrado el producto.

Pero esto lo que hace es crear "agujeros" en la lista y además entonces la variable "contador" pierde algo de utilidad. Esta variable no solo ha de contar los Productos que tenemos, también nos resulta interesante que nos sirva para saber que entre la posición 0 y "contador", hay Productos creados.
Y que a partir de "contador" solo hay valores null.
Por esto no nos interesa tener "agujeros" en la lista, así que borrar un producto no será tan fácil como ponerlo a null. Vamos a elaborarlo un poco más y moveremos de posición todos los elementos tras el elemento borrado, para que no hayan "agujeros".

Para conseguir esto, en realidad, lo más fácil es crear una nueva lista auxiliar con las nuevas posiciones corregidas y luego asignarla como lista principal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public boolean borarProducto(int pos) {
 
    	if (pos < 0 || pos >= lista.length || lista[pos] == null)
    		/*
    		 * Nos han dado una posicion fuera de rango
    		 * o bien no hay Producto en esa posicion
    		 */
    		return false;
    	else {
 
	    	Producto[] listaAux = new Producto[lista.length];
	    	int indiceAux = 0;
 
	    	for (int j = 0; j < contador; j++) {
	    		/*
	    		 * Solo copiamos Productos de posiciones hasta donde diga contador
	    		 * y omitiendo el Producto indicado por el parámetro pos
	    		 */
	    		if (j != pos) {
	    			listaAux[indiceAux] = lista[j];
	    			indiceAux++;
	    		}
	    	}
	    	//Finalizado el for, el Producto ha sido "borrado
	    	lista = listaAux;
	    	contador--;
	        return true;
    	}
    }

Aprovecho para recordar que si en lugar de un array simple, estuvieramos usando alguna colección dinámica, para borrar un Producto solo necesitaríamos UNA instrucción


Siguiente es borrar de nuevo un Producto, pero esta vez según el nombre que nos den.
El código sería parecido al anterior, pero surge una duda. ¿Qué pasa si existe más de un Producto con el mismo nombre?
¿Borramos todos? ¿Ninguno?

En fin, no es buena idea complicarse la vida más de lo necesario y lo que haremos será borrar el primero que encontremos.
De hecho, fíjate si nos vamos a poner fáciles las cosas, que lo que haremos será obtener la posición del Producto que tenga ese nombre, y le pasaremos dicha posición al método de borrado que hemos escrito anteriormente.
Total, es tontería volver a escribir prácticamente el mismo código. Reutilizar es de sabios...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public boolean borrarProducto(String nombre) {
        int posicion = -1; //Empezamos con una posición "imposible"
        //Buscamos coincidencia para saber la posición del producto a borrar.
        for (int j = 0; j < contador; j++)
        	if (lista[j].getNombre().contentEquals(nombre)) {
        		posicion = j;
        		break; //Fin de la búsqueda
        	}
        //Comprobamos lo que hemos encontrado
        if (posicion == -1) {
        	/*
        	 * Si aún tenemos la posición "imposible"
        	 * es que no hay productos con ese nombre.
        	 * No hay nada que borrar
        	 */
        	return false;
        }
        else //Tenemos una posicion, se la pasamos al otro método
        	return borarProducto(posicion);
    }


Insisto en que escribiendo los métodos de borrado de esta manera, nos aseguramos de que nuestra Lista no tendrá agujeros.
Desde 0 hasta "contador" tendremos siempre Productos válidos. Después de "contador", solo habrá posiciones null

Siguiente método, devolver un objeto Producto a partir de la posición indicada.
Esto es fácil, la única comprobación que debemos hacer primero, es comprobar que no nos han dado una posición fuera de rango, parecido a como hicimos en el primer método de borrarProducto.
Esta comprobación es importante porque si nuestra lista es de 10 productos, y nos dan como valor de posición el número 12 por ejemplo, si intentamos acceder a esa posición el programa sufrirá una excepción tipo ArrayIndexOutOfBounds.
Lo mismo si nos dan una posición con valor negativo.

Así que o bien comprobamos que nos dan una posición dentro del rango, o bien usamos try catch para capturar la excepción y evitar que el programa se "rompa".
Yo siempre prefiero, si es posible, "evitar" antes que "capturar"

1
2
3
4
5
6
7
public Producto getProducto(int pos) {
 
    	if (pos < 0 || pos >= lista.length) //Fuera de rango
    		return null;
    	else
    		return lista[pos]; //Ojo, aquí también podemos recibir null, si la posicion indicada es >= que contador
    }

No lo he puesto, pero quizás no estaría de más haber incluido un System.out.println("Posicion fuera de rango") para informar al usuario de que la posición nos ha dado no es válida.


Por último, otro método para devolver Producto, pero a través del nombre.
Si lo piensas podemos hacer lo mismo que con el segundo método de borrado, averiguar la posición y pasársela al primer método de getProducto que acabamos de escribir

Seguro que esto, ya sabes hacerlo tú.

Pregunta lo que sea, si aún tienes dudas.

Un saludo
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
3
Comentar
sin imagen de perfil
Val: 23
Ha disminuido 1 puesto en Java (en relación al último mes)
Gráfica de Java

Estoy estancado, una ayuda por favor

Publicado por Pedro (9 intervenciones) el 03/09/2019 05:38:48
Gracias por tu aporte, me fué de mucha ayuda, pude comprender mejor algunas cosas.
Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar