Ya estoy inscrito ¿Todavía no tienes acceso? Nuestros Planes
Ya estoy inscrito ¿Todavía no tienes acceso? Nuestros Planes
1
respuesta

Java: trabajando con lambdas, streams y Spring Framework

Este código implementa un programa en Java que busca información de series y episodios utilizando la API OMDb, procesando los datos con Streams y Collectors. A continuación, se lista un temario clave de aprendizaje:

  1. Consumo de APIs con HttpClient

    • Se realiza una consulta a la API OMDb para obtener datos de una serie y sus temporadas.
    • Se manipulan respuestas JSON usando clases modelo (DatosSerie, DatosTemporadas, DatosEpisodio).
  2. Uso de Streams y operaciones funcionales

    • flatMap(): Convierte listas anidadas de episodios en una lista única.
    • filter(): Filtra datos para excluir valores no relevantes (N/A en evaluaciones).
    • sorted(): Ordena episodios según evaluación, de mayor a menor.
    • map(): Transforma títulos a mayúsculas para mejorar presentación.
    • collect(): Convierte Streams en listas y agrupa promedios de evaluación por temporada.
  3. Expresión Lambda y Collectors

    • Se agrupan evaluaciones de episodios por temporada con groupingBy().
    • Se obtiene estadísticas globales (max, min, average) con summarizingDouble().
  4. Uso de Optional para búsqueda de datos

    • Se busca un episodio por título parcial usando findFirst().
    • Se maneja el resultado con isPresent() para evitar errores por valores nulos.
  5. Manipulación de fechas con LocalDate

    • Se usa DateTimeFormatter para estandarizar la salida de fechas.
    • Se filtran episodios según fecha de lanzamiento.
public class Principal {
    private Scanner scan = new Scanner(System.in);
    private ConsumoAPI consumoApi = new ConsumoAPI();
    private final String URL_BASE = "http://www.omdbapi.com/?t=";
    private final String API_KEY = "&apikey=16e25129";
    private ConvierteDatos conversor = new ConvierteDatos();

    public void muestraMenu(){
        System.out.println("Ingresa el nombre de la serie que deseas buscar");

        //Busca los datos generales de la serie
        var nombreSerie = scan.nextLine();
        var json = consumoApi.obtenerDatos(URL_BASE + nombreSerie.replace(" ", "+") + API_KEY);
        var datos = conversor.obtenerDatos(json, DatosSerie.class);

        //Busca los datos de todas las temporadas
        List<DatosTemporadas> temporadas = new ArrayList<>();
        for (int i = 1; i <= datos.totalDeTemporadas(); i++) {
            json = consumoApi.obtenerDatos(URL_BASE + nombreSerie.replace(" ", "+") + "&Season="+i+API_KEY);
            var datosTemporadas = conversor.obtenerDatos(json, DatosTemporadas.class);
            temporadas.add(datosTemporadas);
        }
        //temporadas.forEach(System.out::println);

        //Mostrar solo el titulo de los episodio para las temporadas
        //Mejora usando funciones Lambda

        //temporadas.forEach(t -> t.episodios().forEach(e -> System.out.println(e.titulo())));

        List<DatosEpisodio> datosEpisodios = temporadas.stream()
                .flatMap(t -> t.episodios().stream())
                .collect(Collectors.toList());        

        //Convirtiendo los datos a una lista del tipo Episodio
        List<Episodio> episodios = temporadas.stream()
                .flatMap(t -> t.episodios().stream()
                        .map(d -> new Episodio(t.numero(),d)))
                .collect(Collectors.toList());


        //LocalDate fechaBusqueda = LocalDate.of(fecha, 1, 1);

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy");
       
        //Busca episodio por un pedazo del titulo
        //System.out.println("Ingresa el titulo que desea ver: ");
        //var pedazoTQitulo = scan.nextLine();
        //Optional<Episodio> episodioBuscado = episodios.stream()
        //        .filter(e -> e.getTitulo().toUpperCase().contains(pedazoTQitulo.toUpperCase()))
        //        .findFirst();
        //if(episodioBuscado.isPresent()){
        //    System.out.println("Episodio encontrado");
        //    System.out.println("Los datos son: " + episodioBuscado.get());
        //}
        //else {
        //    System.out.println("Episodio no encontrado");
        //}

        Map<Integer, Double> evalucionPorTemporada = episodios.stream()
                .filter(e -> e.getEvaluacion() > 0.0)
                .collect(Collectors.groupingBy(Episodio::getTemporada,
                        Collectors.averagingDouble(Episodio::getEvaluacion)));

        System.out.println(evalucionPorTemporada);
        DoubleSummaryStatistics est = episodios.stream()
                .filter((e -> e.getEvaluacion() > 0.0))
                .collect(Collectors.summarizingDouble(Episodio::getEvaluacion));
        System.out.println("Hoy: " + LocalDate.now().format(dtf));
        System.out.println("Media: " + est.getAverage());
        System.out.println("Mejor evaluado: " + est.getMax());
        System.out.println("Peor evaluado: " + est.getMin());

    }
}
1 respuesta

¡Hola, Diego, espero que estés bien!

Parece que estás trabajando en un proyecto muy interesante que combina el uso de lambdas, streams y el consumo de APIs en Java. Vamos a ver cómo puedes avanzar con la generación de estadísticas utilizando DoubleSummaryStatistics.

En tu código, ya estás utilizando DoubleSummaryStatistics para obtener estadísticas sobre las evaluaciones de los episodios. Aquí está un resumen de lo que estás haciendo:

DoubleSummaryStatistics est = episodios.stream()
    .filter(e -> e.getEvaluacion() > 0.0)
    .collect(Collectors.summarizingDouble(Episodio::getEvaluacion));
System.out.println("Media: " + est.getAverage());
System.out.println("Mejor evaluado: " + est.getMax());
System.out.println("Peor evaluado: " + est.getMin());

Este fragmento de código filtra los episodios con una evaluación mayor a 0 y luego recoge estadísticas como la media, el máximo y el mínimo de las evaluaciones. Es una excelente manera de obtener una visión general de las evaluaciones de los episodios.

Para mejorar aún más tu comprensión y práctica con streams, puedes utilizar el método peek para observar los datos en diferentes etapas del flujo. Aquí tienes un ejemplo de cómo podrías integrarlo:

episodios.stream()
    .peek(e -> System.out.println("Episodio antes de filtrar: " + e))
    .filter(e -> e.getEvaluacion() > 0.0)
    .peek(e -> System.out.println("Episodio después de filtrar: " + e))
    .collect(Collectors.summarizingDouble(Episodio::getEvaluacion));

El método peek es útil para depurar y entender cómo se transforman los datos a lo largo del stream. Recuerda que peek está diseñado principalmente para operaciones de depuración, así que asegúrate de removerlo o comentarlo en el código de producción.

Espero que estas sugerencias te sean útiles y te ayuden a avanzar en tu aprendizaje. ¡Bons estudos!