Sie sind auf Seite 1von 12

JAVA: RECORRIDO DE UN ARREGLO

CONTEXTO
Una de las tareas más comunes en programación, es el trabajo con
arreglos. Y en este contexto, lo que necesitamos es recorrer sus
elementos.
Existen varias opciones para recorrer un arreglo:
 Recorrido indexado.
 Recorrido tipo colección.
 Expresiones Lambda
RECORRIDO INDEXADO
A continuación tienes un ejemplo de como usar el recorrido indexado:
public class Prueba01 {

public static void main(String[] args) {

int[] notas = {56,43,56,12,89,65,23};

// Recorrido indexado de un arreglo


for (int i = 0; i < notas.length; i++) {
int nota = notas[i];
System.out.println(i + ".- " + notas[i]);
}

}
RECORRIDO TIPO COLECCIÓN
Conocido como for each. A continuación tienes un ejemplo de como usar
el recorrido tipo colección:
public class Prueba02 {

public static void main(String[] args) {

int[] notas = {56,43,56,12,89,65,23};

// Recorrido tipo colección


for (int nota : notas) {
System.out.println("nota: " + nota);
}

}
EXPRESIONES LAMBDA
A continuación tienes un ejemplo de cómo usar las expresiones lambda en
el recorrido de un arreglo:
public class Prueba03 {

public static void main(String[] args) {

int[] notas = {56,43,56,12,89,65,23};

// Usando Programación Funcional


Arrays.stream(notas)
.forEach(n -> System.out.println("Nota: " + n) );

}
La ventaja de las expresiones lambda, es que puedes aplicar operaciones,
como por ejemplo filtros. A continuación tienes un ejemplo:
public class Prueba04 {

public static void main(String[] args) {


int[] notas = {56,43,56,12,89,65,23};

// Usando Programación Funcional


Arrays.stream(notas)
.filter(n -> n > 50)
.forEach(n -> System.out.println("Nota: " + n) );

}
Utilizando expresiones lambda, puedes encontrar muchas mas ventajas.

Lambda Expressions
A block of code that you can pass around so it can be executed later, once
or multiple times.

 Anonymous methods.
 Reduce verbosity caused by anonymous classes.

- Alonzo Church in his invention of the lambda calculus in 1936. - Lisp 1958
- Supported in C#, JavaScript, Python, Ruby, C++11
How are they different from Java methods?

Lambdas

(int x, int y) -> x + y

() -> 42

(String s) -> {System.out.println(s);}

- Omission of brackets and return statement - Return type deduction

Lambdas

Examples
Before

Button btn = new Button();


final PrintStream pStream = ...;
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
pStream.println("Button Clicked!");
}
});

After

Button btn = new Button();


final PrintStream pStream = ...;
btn.setOnAction(e -> pStream.println("Button Clicked!"));

- Argument type deduction - In-place implementation. - Local variable


capturing - Multiple lines lambdas

Lambdas

Examples

List<String> strs = ...;


Collections.sort(strs, (s1, s2) ->
Integer.compare(s1.length(), s2.length()));
new Thread(() -> {
connectToService();
sendNotification();
}).start();
Functional Interfaces
Single Abstract Method Type

Functional Interfaces

Example

@FunctionalInterface
public interface Runnable {
public void run();
}

Runnable r = () -> System.out.println("Hello World!");

- @FunctionalInterface - May be omitted - Generates error when there is


more than one abstract method - Attributing a lambda expression to a
variable - Returning a lambda expression is also possible

java.util.function

 Predicate<T> - a boolean-valued property of an object


 Consumer<T> - an action to be performed on an object
 Function<T,R> - a function transforming a T to a R
 Supplier<T> - provide an instance of a T (such as a factory)
 UnaryOperator<T> - a function from T to T
 BinaryOperator<T> - a function from (T,T) to T- More meaningful type
names

Method References
Treating an existing method as an instance of a Functional Interface
- Object oriented way of attributing a method to a variable

Method References

Examples

class Person {
private String name;
private int age;

public int getAge() {return this.age;}


public String getName() {return this.name;}
}

Person[] people = ...;


Comparator<Person> byName = Comparator.comparing(Person::getName)
;
Arrays.sort(people, byName);

- :: operator

Method References

Kinds of method references

 A static method (ClassName::methName)


 An instance method of a particular object (instanceRef::methName)
 A super method of a particular object (super::methName)
 An instance method of an arbitrary object of a particular type
(ClassName::methName)
 A class constructor reference (ClassName::new)
 An array constructor reference (TypeName[]::new)- "Instance
method of an arbitrary object" adds an argument of that type which
becomes the receiver of the invocation

Method References

More Examples

Consumer<Integer> b1 = System::exit;
Consumer<String[]> b2 = Arrays::sort;
Consumer<String> b3 = MyProgram::main;
Runnable r = MyProgram::main;

Default Methods
Add default behaviours to interfaces

Why default methods?


Java 8 has lambda expressions. We want to start using them:

List<?> list = ...


list.forEach(...); // lambda code goes here

There's a problem
The forEach method isn’t declared by java.util.List nor the
java.util.Collection interface because doing so would break existing
implementations.

Default Methods
We have lambdas, but we can't force new behaviours into the current
libraries.
Solution: default methods.

Default Methods

 Traditionally, interfaces can't have method definitions (just


declarations).
 Default methods supply default implementations of interface
methods.

Examples

Example 1

Basics

public interface A {
default void foo() {
System.out.println("Calling A.foo()");
}
}

public class Clazz implements A {


}

Client code

Clazz clazz = new Clazz();


clazz.foo();

Output

"Calling A.foo()"

Example 2

Getting messy

public interface A {

default void foo(){


System.out.println("Calling A.foo()");
}
}

public interface B {

default void foo(){


System.out.println("Calling B.foo()");
}

}
public class Clazz implements A, B {
}

Does this code compile?


Of course not (Java is not C++)!
class Clazz inherits defaults for foo() from both types A and B
How do we fix it?
Option A:

public class Clazz implements A, B {


public void foo(){/* ... */}
}

We resolve it manually by overriding the conflicting method.


Option B:

public class Clazz implements A, B {


public void foo(){
A.super.foo(); // or B.super.foo()
}
}

We call the default implementation of method foo() from either interface


A or B instead of implementing our own.
Going back to the example of forEach method, how can we force it's default
implementation all the iterable collections?
Let's take a look at the Java UML for all the iterable Collections:
In order to add a default behaviour to all the iterable collections, a default
forEach method was added to the Iterable<E> interface.
We can find its default implementation in java.lang.Iterable interface:

@FunctionalInterface
public interface Iterable {
Iterator iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}

The forEach method takes a java.util.function.Consumer functional


interface type as a parameter, which enables us to pass in a lambda or a
method reference as follows:

List<?> list = ...


list.forEach(System.out::println);

This is also valid for Sets and Queues, for example, since both classes
implement the Iterable interface.

Summary

 Default methods can be seen as a bridge between lambdas and JDK


libraries.
 Can be used in interfaces to provide default implementations of
otherwise abstract methods.
o Clients can optionally implement (override) them.
 static methods are now also allowed in interfaces.
o Can eliminate the need for utility classes like Collections.

Accumulators
Scalable updatable variables
Accumulators
The continual evolution of uses of concurrency and parallelism in
applications requires continual evolution in library support. For this
purpose, the Accumulators were introduced.

Accumulators
Maintaining a single count, sum, etc., that is updated by possibly many
threads is a common scalability problem.
A set of new classes were created for that purpose:

 DoubleAccumulator
 DoubleAdder
 LongAccumulator
 LongAdder

Accumulators
Package java.util.concurrent mechanisms synchronized operations
between threads, however if all you want to do is increment a variable
across threads, it was overkill and then some.
These classes are usually preferable to alternatives when multiple threads
update a common value that is used for purposes such as summary
statistics that are frequently updated but less frequently read.

Accumulators
Both the DoubleAdder and LongAdder classes can be seen as specific
subsets of the DoubleAccumulator and LongAccumulator functionality.
The call new DoubleAdder() is equivalent to:
new DoubleAccumulator((x, y) -> x + y, 0.0).
The call new LongAdder() is equivalent to:
new LongAccumulator((x, y) -> x + y, 0L).

Examples

DoubleAccumulator da = new DoubleAccumulator((x,y) -> x + y, 0.0);


List<Double> doubles = Arrays.asList(1.0, 2.0, 3.0, 4.0, 10.0);
doubles.forEach(da::accumulate);
System.out.println("Result: " + da.doubleValue());

Output:

Result: 20
LongAdder la = new LongAdder();
List<Long> longs = Arrays.asList(10L, 20L, 30L, 40L, 100L);
longs.forEach(la::add);

System.out.println("Result: " + la.longValue());

Output:

Result: 200

Das könnte Ihnen auch gefallen