Operador de dos puntos doble (::) en Java 8

el doble colon :: El operador se introduce en Java 8 para referencia de métodos. Esta es una sintaxis abreviada para la expresión lambda que ejecuta un método. Puede escribir un código más compacto y legible utilizando el operador de dos puntos en comparación con las clases anónimas y la expresión lambda. Entenderemos su uso con muchos ejemplos.

Índice
  1. 1. Información general
  2. 2. Método estático
  3. 3. Método de instancia
  4. 4. constructor
  5. 5. Súper Método
  6. 6. Ejemplo práctico del mundo real
  7. 7. Cierre

1. Información general

requisitos previos

Debe tener un conocimiento básico de interfaz funcional, expresiones lambda y arroyos para entender estos ejemplos, de lo contrario no te preocupes, también aprenderás estos conceptos en el camino.

La doble coma se refiere a un método.

Dos puntos :: básicamente se refiere a un único método, y este único método puede ser un

  1. Un método estático ClassName::staticMethodName
    por ejemplo, Integer.parseInteger, Double.parseDouble
  2. Un método de instancia Object::instanceMethodName
    por ejemplo System.out::println, String::toUpperCase
  3. Un constructor ClassName::new
  4. un gran método super::parentMethodName
La doble coma devuelve una interfaz funcional.

Dos puntos :: siempre devuelve una interfaz de trabajo. Hay dos formas de usar esta interfaz funcional devuelta:

  1. Usa esto para inicializar una interfaz funcional y luego realizar una función.
    Aquí usamos la interfaz funcional incorporada de Java como Function, Supplier, Consumer, BiFunction o creamos nuestra interfaz funcional personalizada usando @FunctionalInterface anotación.
  2. Usa esto para reemplazar expresión lambda en arroyos.

No se preocupe si esto parece demasiado complicado. Profundicemos en los ejemplos para entenderlos mejor.

2. Método estático

Sintaxis
// Lambda expression 
(args) -> ClassName.staticMethodName(args)

// Method Reference
ClassName::staticMethodName

2.1 Calculadora

Vamos a crear dos estático métodos square y multiply dentro Calculator clasificar.

class Calculator {
	
    public static double square(double num){
       return Math.pow(num, 2);
    }
    public static double multiply(double num1, double num2) {
    	return num1*num2;
    }
}
2.1.1 Inicializar la interfaz funcional

Inicialicemos java incrustado Function, BiFunction interfaz funcional y aplicarlo para encontrar el cuadrado y multiplicar respectivamente.
Function la interfaz acepta un argumento y devuelve un argumento. Aquí toma un argumento doble y devuelve su cuadrado.
BiFunction interfaz acepta dos argumentos y devuelve un argumento. Aquí toma dos argumentos dobles y devuelve su multiplicación.

// Initialize functional interface
Function<Double, Double> square = Calculator::square;
BiFunction<Double, Double, Double> multiply = Calculator::multiply;

// Execute function
square.apply(3.0);
multiply.apply(2.5, 5.0)

Output

9.0 12.5
2.1.2 Reemplazar expresión lambda

Generamos el cuadrado de la lista de enteros reemplazando la expresión lambda con la referencia del método.

List<Integer> numbers = Arrays.asList(1,2,3);

// Lambda expression 
numbers.stream().map(number -> Calculator.square(number)).forEach(number -> System.out.println(number));
		
// Method Reference
numbers.stream().map(Calculator::square).forEach(System.out::println);

Output

1.0 4.0 9.0

2.2 Entero::parseInt

Sabemos que parseInt es un método estático en Integer clasificar.

2.2.1 Inicializar la interfaz funcional

Inicialicemos java incrustado Function interfaz funcional y aplicarlo para analizar String to Integer.
Function interfaz toma un argumento y devuelve un argumento. Aquí, por ejemplo, se necesita un cadena de caracteres argumentos y devoluciones Entero.

// Initialize functional interface
Function<String, Integer> parseInt = Integer::parseInt;

// Execute function
parseInt.apply("2019");

Output

2019
2.2.2 Reemplazar expresión lambda

Analicemos una lista de cadenas en Entero usando su estática parseInt método. Vemos cómo podemos reemplazar la expresión lambda con una referencia de método que da como resultado el mismo resultado.

List<String> years = Arrays.asList("2019", "2020", "2021");

// Lambda Expression
years.stream().map(year -> Integer.parseInt(year)).forEach(year -> System.out.println(year));

// Method Reference
years.stream().map(Integer::parseInt).forEach(System.out::println);

Output

2019 2020 2021

3. Método de instancia

Sintaxis
// Lambda expression 
(args) -> object.instanceMethodName(args)

// Method Reference
object::instanceMethodName

3.1 Calculadora

Vamos a crear dos ejemplo métodos square y multiply dentro Calculator clasificar.

class Calculator {
	
    public double square(double num){
       return Math.pow(num, 2);
    }
    public double multiply(double num1, double num2) {
    	return num1*num2;
    }
}
3.1.1 Inicializar la interfaz funcional

Inicialicemos java incrustado Function, BiFunction interfaz funcional y aplicarlo para encontrar el cuadrado y multiplicar respectivamente.

// Initialize functional interface
Function<Double, Double> square = new Calculator()::square;
BiFunction<Double, Double, Double> multiply = new Calculator()::multiply;

// Execute function
square.apply(3.0);
multiply.apply(2.5, 5.0)

Output

9.0 12.5
3.1.2 Reemplazar expresión lambda

Generamos el cuadrado de la lista de enteros reemplazando la expresión lambda con la referencia del método.

List<Integer> numbers = Arrays.asList(1,2,3);

// Lambda expression 
numbers.stream().map(number -> new Calculator().square(number)).forEach(number -> System.out.println(number));
		
// Method Reference
numbers.stream().map(new Calculator()::square).forEach(System.out::println);

Output

1.0 4.0 9.0

3.2 Sistema.out::println

3.2.1 Inicializar la interfaz funcional

Inicialicemos java incrustado Supplier interfaz funcional para imprimir una cadena.
Supplier la interfaz acepta un argumento y no devuelve nada. Aquí, como ejemplo, acepta un cadena de caracteres argumento e imprimirlo.

// Initialize functional interface
Consumer<String> println = System.out::println;

// Execute function
println.accept("Learning Method Reference a.k.a Colon Operator ::");

Output

Learning Method Reference a.k.a Colon Operator ::
3.2.2 Anular clase anónima y expresión Lambda

Imprimiremos una lista de Strings y veremos cómo los dos puntos dobles :: La referencia del método hace que el código sea más conciso y legible en comparación con la clase anónima y la expresión lambda.

List<String> languages = Arrays.asList("java", "javascript", "css");

// Anonymous Class
languages.forEach(new Consumer<String>() {         
    @Override
    public void accept(String str) {
        System.out.println(str);
    }
});

// Lambda expression 
languages.forEach(str -> System.out.println(str)); 

// Method Reference
languages.forEach(System.out::println);            

Output

java javascript css
3.2.3 Imprimir una lista de números enteros

Imprimamos una lista de enteros usando la expresión lambda y los dos puntos dobles :: referencia del método.

List<Integer> numbers = Arrays.asList(1,2,3);

// Lambda expression 
numbers.forEach(number->System.out.println(number));

// Method Reference
numbers.forEach(System.out::println);

Output

1 2 3

3.3 Cadena :: a Mayúsculas

3.3.1 Inicializar la interfaz funcional

Inicialicemos java incrustado Function interfaz funcional y ejecútelo para cambiar String a MAYÚSCULAS.

// Initialize functional interface
Function<String, String> toUpperCase = String::toUpperCase;

// Execute function
toUpperCase.apply("java");

Output

JAVA
3.3.2 Reemplazar expresión lambda

Veamos el ejemplo en el que usamos varias referencias a métodos para imprimir la cadena en mayúsculas.

List<String> languages = Arrays.asList("java", "javascript", "css");

// Lambda expression
languages.stream().map(str -> str.toUpperCase()).forEach(str -> System.out.println(str));

// Method Reference
languages.stream().map(String::toUpperCase).forEach(System.out::println);          

Output

JAVA JAVASCRIPT CSS

4. constructor

Dos puntos :: El operador se puede usar para crear una instancia llamando al constructor.

Sintaxis
ClassName::new

4.1 Creando un int[10] desplegar

// Default
int[] array1 = new int[10];

// Method Reference
IntFunction<int[]> arrayMaker = int[]::new;
int[] array2 = arrayMaker.apply(10);

4.2 Crear un mapa hash

// Default
Map map1 = new HashMap();

// Method Reference
Supplier<Map> mapMaker = HashMap::new;
Map map2 = mapMaker.get();

5. Súper Método

Sintaxis
super::parentMethodName

Nosotros creamos cuadrado y multiplicar métodos de instancia en Calculator clase y luego llame a estos métodos en nuestro heredado AdvanceCalculator clase usando super::parentMethodName crear métodos avanzados cuadradoYAñadir y cuadradoYMultiplicar

class Calculator {
	
    public double square(double num){
       return Math.pow(num, 2);
    }
    
    public double multiply(double num1, double num2) {
    	return num1*num2;
    }
}

class AdvanceCalculator extends Calculator {
	
	public double squareAndAdd(double num1, double num2) {
    	Function<Double, Double> square = super::square; 	
    	return square.apply(num1) + square.apply(num2);
    }
	
	public double squareAndMultiply(double num1, double num2) {
    	Function<Double, Double> square = super::square; 
    	BiFunction<Double, Double, Double> multiply = super::multiply;
    	return multiply.apply(square.apply(num1), square.apply(num2));
    }
}

6. Ejemplo práctico del mundo real

Vamos a crear una clase Tutorial con nombre, duración y ranking de propiedades.

class Tutorial {

  private String name;
  private Integer duration;
  private Double rating;

  public Tutorial(String name) {
    this.name = name;
    this.duration = 0;
    this.rating = 0.0;
  }
  
  public Tutorial(String name, Integer duration) {
    this.name = name;
    this.duration = duration;
    this.rating = 0.0;
  }
  
  public Tutorial(String name, Integer duration, Double rating) {
    this.name = name;
    this.duration = duration;
    this.rating = rating;
  }
  
  public String getName() {
    return name;
  }	
  public void setName(String name) {
    this.name = name;
  }
  public Integer getDuration() {
    return duration;
  }
  public void setDuration(Integer duration) {
    this.duration = duration;
  }
  public Double getRating() {
    return rating;
  }
  public void setRating(Double rating) {
    this.rating = rating;
  }
  
  @Override
  public String toString() {
    return "Tutorial[ " + name + "t- " + duration + "min, rating=" + rating + " ]";
  }

  public static int compareByRating(Tutorial t1, Tutorial t2) {
    return t1.getRating().compareTo(t2.getRating());
  }

  public static int compareByDuration(Tutorial t1, Tutorial t2) {
    return t1.getDuration().compareTo(t2.getDuration());
  }
}

Vamos a crear una lista de objetos tutoriales: -

// List of tutorials
List<Tutorial> tutorials = Arrays.asList(new Tutorial[] {
    new Tutorial("Streams in Java 8", 30, 4.2),
    new Tutorial("What's new in Java 11", 25, 4.8),
    new Tutorial("Core Java Concepts", 45, 3.5)});

6.1 Imprimir la lista de tutoriales

// Lambda Expression
tutorials.forEach(tutorial -> System.out.println(tutorial));

// Method Reference
tutorials.forEach(System.out::println);

Output

Tutorial[ Streams in Java 8 - 30min, rating=4.2 ] Tutorial[ What's new in Java 11 - 25min, rating=4.8 ] Tutorial[ Core Java Concepts - 45min, rating=3.5 ]

6.2 Obtener una lista de nombres de tutoriales en mayúsculas

// Lambda Expression
tutorials.stream().map(tutorial -> tutorial.getName()).map(name -> name.toUpperCase()).forEach(s -> System.out.println(s));

// Method Reference
tutorials.stream().map(Tutorial::getName).map(String::toUpperCase).forEach(System.out::println);

Output

STREAMS IN JAVA 8 WHAT'S NEW IN JAVA 11 CORE JAVA CONCEPTS

6.3 Ordenar tutoriales por clasificación

// Lambda Expression
tutorials.stream().sorted((tutorial1, tutorial2) -> Tutorial.compareByRating(tutorial1, tutorial2)).forEach(tutorial -> System.out.println(tutorial));

// Method Reference
tutorials.stream().sorted(Tutorial::compareByRating).forEach(System.out::println);	

Output

Tutorial[ Core Java Concepts - 45min, rating=3.5 ] Tutorial[ Streams in Java 8 - 30min, rating=4.2 ] Tutorial[ What's new in Java 11 - 25min, rating=4.8 ]

6.4 Ordenar tutoriales por duración

// Lambda Expression
tutorials.stream().sorted((tutorial1, tutorial2) -> Tutorial.compareByDuration(tutorial1, tutorial2)).forEach(tutorial -> System.out.println(tutorial));

// Method Reference
tutorials.stream().sorted(Tutorial::compareByDuration).forEach(System.out::println);	

Output

Tutorial[ What's new in Java 11 - 25min, rating=4.8 ] Tutorial[ Streams in Java 8 - 30min, rating=4.2 ] Tutorial[ Core Java Concepts - 45min, rating=3.5 ]

6.5 Crear una nueva instancia del tutorial

Cada referencia de método constructor devuelve una interfaz funcional. El constructor de un argumento devuelve Function y el constructor de dos argumentos devuelve BiFunction la interfaz funcional se proporciona de forma predeterminada en Java 8, por lo que creamos TriFunction Interfaz funcional por nosotros mismos para llamar al constructor de tres argumentos.

@FunctionalInterface
interface TriFunction<A, B, C, R> { 
    R apply(A a, B b, C c); 
    default <V> TriFunction<A, B, C, V> andThen( Function<? super R, ? extends V> after) { 
        Objects.requireNonNull(after); 
        return (A a, B b, C c) -> after.apply(apply(a, b, c)); 
    } 
}
// Create an instance from one arg constructor
Function<String, Tutorial> tutorial1 = Tutorial::new;
Tutorial t1 = tutorial1.apply("Tutorial 1");

// Create an instance from two arg constructor
BiFunction<String, Integer, Tutorial> tutorial2 = Tutorial::new; 
Tutorial t2 = tutorial2.apply("Tutorial 2", 25);

// Create an instance from three arg constructor
TriFunction<String, Integer, Double, Tutorial> tutorial3 = Tutorial::new;
Tutorial t3 = tutorial3.apply("Tutorial 3", 30, 4.9);

Arrays.asList(t1, t2, t3).forEach(System.out::println);

Output

Tutorial[ Tutorial 1 - 0min, rating=0.0 ] Tutorial[ Tutorial 2 - 25min, rating=0.0 ] Tutorial[ Tutorial 3 - 30min, rating=4.9 ]

7. Cierre

En este artículo, hemos visto cómo usar el operador de dos puntos introducido en Java 8. Es muy útil mantener su código conciso y legible, especialmente en secuencias donde puede reemplazar expresiones lambda con una referencia de método para usar el operador de dos puntos. .

IDE modernos como Eclipse (Función de reparación rápida) e IntelliJ IDEA (Función de intención) proporcionar compatibilidad integrada para convertir la expresión lambda en una referencia de método equivalente.

Si quieres conocer otros artículos parecidos a Operador de dos puntos doble (::) en Java 8 puedes visitar la categoría Tutoriales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas