Giter Site home page Giter Site logo

java_learning_notes's Introduction

JAVA LEARNING NOTES

x Sebastián Kravetz @wwiiddeeweb

Data Structures

➡️ EJERCICIOS

  • ArrayList (orden de inserción)
  • Stack (last in, first out - LIFO)
  • Queue (first in, first out - FIFO)
  • LinkedList (orden de inserción)
  • Set (no garantiza orden)
  • Map (orden por llaves)

Generics

Se definen con el operador de diamantes <>

  1. Nos ayudan reforzar el checkeo de datos en tiempo de compilación.

    Su existencia se relaciona con el riesgo de operaciones de casting en la que el compilador no puede asegurar la integridad del tipado. Los generics tienen su razón de ser sólo para reforzar las reglas del compilador y asegurar la consistencia de los tipos de datos.

    • Ejemplo: En una estructura de datos como ArrayList nos permite asegurar qué tipo de datos se almacenarán en esta estructura.
    // 👎
    
    List aGenericList = new ArrayList();
    aGenericList.add("1"); // crashea en runtime
    aGenericList.add(1);
    
    // 👍
    
    List<Integer> aNumbersList = new ArrayList<>();
    aNumbersList.add(1);
    aNumbersList.add("1"); // el compilador no permitirá esto, seremos notificados por el IDE antes de ejecutar el programa.

  1. Para generalizar el tipado de una estructura, existen:
    1. Type parameters: Son los placeholders que indican en donde debe especificarse un tipo concreto de datos, ejemplo:
       public interface Map<K, V> 
    // en donde K= primer type parameter
    // y V= segundo type parameter
    1. Type arguments: Es cuando, en la posición de los placeholders de los type parameters, declaramos el tipo de dato concreto al inicializar una estructura de datos.
       Map<String, Integer> myMap = new HashMap<>();
    // en la posición K declaramos el tipo String
    // en la posición V declaramos el tipo Integer

  1. Convenciones para el nombrado de los type parameters.
    <E>: "Element" -> usado harto en java.lang
    <K>: "Key" -> usado en Map
    <V>: "Value" -> usado en Map
    <N>: "Number"
    <T>: "Type"

  1. Usando generics en clases: ➡️ EJERCICIOS

    public class Box<T> {
    
        private T internalState;
    
        public void setState(T state)
        {
            this.internalState = state;
        }
    
        public T getState()
        {
            return this.internalState;
        }
    }

    Podemos luego, utilizar esta clase con cualquier tipo de dato concreto:

    // EJ4.
    
         Box<Phone> boxOfPhones = new Box<>();
         boxOfPhones.setState(new Phone("Nokia"));
         System.out.println(boxOfPhones.getState());
    // Phone{brand='Nokia'}
    
         Box<Letter> boxOfLetters = new Box<>();
         boxOfLetters.setState(new Letter("Seba"));
         System.out.println(boxOfLetters.getState());
    // Letter{sender='Seba'}
    // EJ5 
    Box<Shape> boxOfRectangles = new Box<>();
    boxOfRectangles.setState(new Rectangle("rectángulo", 22.0, 12.4));
    System.out.println(boxOfRectangles.getState());
    // Rectangle{name='rectángulo', width=22.0, height=12.4}
    
    Box<Shape> boxOfCircles = new Box<>();
    boxOfCircles.setState(new Circle("circulito", 22.0));
    System.out.println(boxOfCircles.getState());
    // Circle{name='circulito', radius=22.0}

    EJ5: En este ejemplo, también estamos poniendo los tipos genéricos al servicio del polimorfismo, utilizando la interfaz Shape en común para los objetos de Rectangle y Circle


  1. Genéricos y métodos: ➡️ EJERCICIOS

    Definiendo tipos de datos genéricos en la implementación de un método:

    1. Generic Type Parameter para ser utilizado como tipado de los parámetros del método.

      public <T> void printValues(T[] valuesArray) {
           for (T element : valuesArray) 
            {
             // something...
            }
      }
    2. Generic Type Parameter para ser utilizado como tipado del retorno del método. El mismo genérico del parámetro del método es también usado para tipar su retorno.

         // ejemplo retorna el mismo tipo:
         public static <T> T getReturnedAsIs(T element)
         // ejemplo retorna una lista que contiene el mismo tipo:
         public static <T> List<T> getReturnedAsList(T[] arr)

  1. Bounded Type Parameters ➡️ EJERCICIOS

    In the context of Java generics, a "bound" refers to a restriction placed on a type parameter. It specifies the types that can be used as arguments for a type parameter in a generic class, interface, or method. Bounds are used to enforce type safety by ensuring that the generic type meets certain criteria, such as being a subclass of a particular class or implementing a particular interface.

    1. Simple Bounded Type:

      Sirven para acotar una definición genérica. Es decir, dado un generic type parameter <T>, podemos decir que este type parameter sólo funcione para ciertos tipos de datos.

      Esto se hace en base a una suerte de "herencia" y/o afinidad. Digamos que que el genérico <T> sólo debería funcionar para la familia de la interfaz List y sus implementaciones, pero no para otras estructuras de datos que no desciendan de List, podríamos decir: <T extends List>

      // Ejemplos:
      // 1. 
      static <T extends Comparable<T>> int countGreaterThan(T[] nums, T min)
      {
          int finalCount = 0;
          for (int i = 0; i < nums.length; i++) {
              if (nums[i].compareTo(min) > 0) finalCount++;
          }
          return finalCount;
      }
      
      // 2. 
      static <T extends List<V>, V> void printsListsOnly(T list)
      {
          list.forEach(System.out::println);
      }
    2. Multiple Bounded Types:

      Acotan aún más lo que debe cumplir el genérico, pudiendo concatenar clases e interfaces para este propósito. Se utiliza el operador & para concatenar los tipos.

      La sintaxis es <T extends Clase & Interfaz & ...>

    Importante: Si se mezclan clases e interfaces, las clases siempre deberán ser el primer argumento del Bounded Type, y sólo puede ser una clase, pero no hay problema con múltiples interfaces.

    // MULTIPLE BOUNDS
    
    static <T extends Collections & List<V>, V> void multipleBoundsToComply(T param)
    {
        System.out.println(param);
    }
    
    // 👍
    List<String> anotherListForChristsSake = new ArrayList<>(Arrays.asList("Bye", "Byex"));
    multipleBoundsToComply(anotherListForChristsSake); // esto funciona! porque anotherListForChristsSake cumple todo lo solicitado en el genérico.
    
    // 👎
    Set<String> anotherMapForChristsSake = new ArrayList<>(Arrays.asList("Bye", "Byex"));
    multipleBoundsToComply(anotherMapForChristsSake);
    // esto no funciona, porque un Set<String> sólo cumple el requisito de Collection pero no el de List
    1. Unbounded Wildcard

      Se escribe con la sintaxis <?>. Permite definir un tipo genérico para dato desconocido, permitiendo cualquier que cualquier tipo de dato sea utilizado.

      // ejemplo:
      static void printLists(List<?> list)
    2. Upper Bounded Wildcard

      Fija un "límite superior" (limita arriba), es decir, permite usar tipos que sean el mismo ó los que están "hacia abajo" (subclases)

      "Type Set Direction: The set of acceptable types is "bounded above" by the specified type. That is, it includes the bound itself and any types that are "below" it in the hierarchy ( subtypes)."

      Sintaxis: <T extends SubClass> o <T extends Interface>

        // UPPER BOUNDS + WILDCARDS
        // Sólo aceptará los tipos que sean Number ó desciendan de él
        static void upperBounds(List<? extends Number> numberList)
        {
            System.out.println(numberList);
        }
    3. Lower Bounded Wildcard

      Fija un "límite inferior" (limita abajo), es decir, permite usar tipos que sean el mismo ó los que están "hacia arriba" en la jerarquía (superclases)

      "Type Set Direction: The set of acceptable types is "bounded below" by the specified type. This means it includes the bound itself and any types that are "above" it in the hierarchy ( supertypes)."

      Sintaxis: <? super SuperClass>

      // LOWER BOUNDS + WILDCARDS
      // Sólo aceptará Number o superclases de Number
      static void lowerBounds(List<? super Number> numberList)
      {
          System.out.println(numberList);
      }
    4. Diferencias entre Wildcards y Bounded Type Parameters:

      1. La unión de tipos (multiple bounds), sólo se puede con bounded type parameters, esto no es posible con wildcards:
        // ejemplo de unión de tipos:
         static <T extends Collections & AnInterface> void method(T param) {}
      2. Los bounded type parameters sólo tienen upper bound (extends), pero no se puede usar el lower bound (super), ya que esto es exclusivo de los wildcards.
      3. Los wildcards NO permiten "capturar" un tipo para luego ser reutilizado en el mismo contexto de manera que se conozca su relación con otros tipos. Por ejemplo, no puedes declarar un método que tome un List<?> y luego añadir elementos de ese mismo tipo desconocido a la lista, porque el compilador no puede asegurar el tipo de los elementos de forma segura.

Streams API

➡️ EJERCICIOS

Permiten trabajar con un paradigma declarativo y funcional, versus el paradigma imperativo clásico de Java.

Esto significa, por ejemplo al recorrer un arreglo, que no debemos hacernos cargo de definir paso a paso el algoritmo: iniciar un ciclo, fijar contadores, fijar condiciones de límite, fijar condicionales para terminar un recorrido, poblar una lista en base a lo encontrado, etc. En cambio, podremos ejecutar las mismas operaciones desde una perspectiva funcional, utilizando funciones lambda

Componentes de los streams:

  1. Una colección (Collections)
  2. Una serie de operaciones intermedias o "pipes" (Intermediate Operators). Estas son las operaciones concatenables, como map, reduce, filter, etc.
  3. Operadores de finalización (Terminal Operators). Toman el resultado al final de todas las operaciones y lo almacenan en una estructura de datos apropiada.

Nota: Para los ARRAYS también podremos utilizar el Streams API, pero no se pueden usar directamente al no pertenecer a la interfaz Collections, en este caso es necesario utilizar el método Arrays.stream()

java_learning_notes's People

Contributors

rrooddooxx avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.