Skip to content

Vavr 1.0: configuración y primeros pasos

Posted on:20 de julio de 2026 at 23:00

Este es el primer capítulo de Dominando Vavr. Vamos a crear un proyecto sencillo, agregar Vavr y utilizar tres piezas fundamentales de la biblioteca: Option, las funciones y las colecciones inmutables.

Si todavía no conoces el objetivo y el temario, puedes leer la introducción a la serie.

Requisitos

Para seguir los ejemplos necesitas:

Vavr 1.0 conserva compatibilidad con Java 8, pero usaremos Java 21 para trabajar con una base moderna y con soporte de largo plazo.

Crear el proyecto

La estructura mínima será la siguiente:

vavr-primeros-pasos/
├── pom.xml
└── src/
    └── main/
        └── java/
            └── net/javabackend/vavr/App.java

Dependencia con Maven

Agrega Vavr 1.0.1 al archivo pom.xml:

<properties>
    <maven.compiler.release>21</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>io.vavr</groupId>
        <artifactId>vavr</artifactId>
        <version>1.0.1</version>
    </dependency>
</dependencies>

Dependencia con Gradle

Si utilizas Gradle, la dependencia equivalente es:

dependencies {
    implementation "io.vavr:vavr:1.0.1"
}

No necesitamos plugins ni configuración adicional para empezar.

Primer ejemplo: representar una ausencia con Option

En Java solemos representar un dato inexistente con null o Optional. Vavr ofrece Option, un valor que puede ser Some —contiene un dato— o None —no contiene nada—.

package net.javabackend.vavr;

import io.vavr.control.Option;

public class App {

    static Option<String> buscarNombre(long id) {
        return id == 1
                ? Option.of("Ada")
                : Option.none();
    }

    public static void main(String[] args) {
        String mensaje = buscarNombre(1)
                .map(String::toUpperCase)
                .map(nombre -> "Usuario: " + nombre)
                .getOrElse("Usuario no encontrado");

        System.out.println(mensaje);
    }
}

El resultado es:

Usuario: ADA

La operación no necesita comprobar null. Cada transformación se ejecuta únicamente cuando existe un valor.

Componer funciones

Vavr incluye interfaces de funciones desde Function0 hasta Function8. Además de representar una función, permiten componerla, memorizar resultados y manejar excepciones.

import io.vavr.Function1;

Function1<String, String> limpiar = String::trim;
Function1<String, String> normalizar = limpiar.andThen(String::toLowerCase);

System.out.println(normalizar.apply("  JAVA BACKEND  "));

El resultado será java backend. La composición ayuda a construir transformaciones a partir de operaciones pequeñas y fáciles de probar.

Colecciones inmutables

Las colecciones de Vavr no modifican la instancia original. Una operación devuelve una nueva colección que puede compartir internamente parte de su estructura con la anterior.

import io.vavr.collection.List;

List<String> lenguajes = List.of("Java", "Kotlin");
List<String> actualizados = lenguajes.append("Scala");

System.out.println(lenguajes);   // List(Java, Kotlin)
System.out.println(actualizados); // List(Java, Kotlin, Scala)

Esta propiedad evita cambios inesperados cuando un valor se comparte entre diferentes partes de la aplicación.

También podemos encadenar operaciones conocidas de los Streams de Java:

List<Integer> resultado = List.rangeClosed(1, 10)
        .filter(numero -> numero % 2 == 0)
        .map(numero -> numero * numero);

System.out.println(resultado); // List(4, 16, 36, 64, 100)

A diferencia de un Stream, List es una colección reutilizable: podemos recorrer resultado más de una vez.

Un ejemplo pequeño de dominio

Combinemos Option y una colección inmutable para buscar un producto:

import io.vavr.collection.List;
import io.vavr.control.Option;

record Producto(long id, String nombre) {}

List<Producto> productos = List.of(
        new Producto(1, "Teclado"),
        new Producto(2, "Monitor")
);

Option<Producto> encontrado = productos
        .find(producto -> producto.id() == 2);

String nombre = encontrado
        .map(Producto::nombre)
        .getOrElse("No encontrado");

System.out.println(nombre); // Monitor

El tipo de retorno deja claro que la búsqueda puede no encontrar un producto. El consumidor decide qué hacer en ese caso.

Cuándo utilizar Vavr

Vavr resulta especialmente útil cuando:

No es necesario reemplazar todas las colecciones, todos los Optional ni cada excepción del proyecto. Empieza en una parte pequeña de la lógica de negocio y evalúa si el resultado es más legible para el equipo.

Siguiente capítulo

Ya tenemos el proyecto configurado y una primera idea de cómo se siente trabajar con Vavr. En el próximo capítulo profundizaremos en sus colecciones inmutables, sus diferencias con las colecciones de Java y el costo real de crear nuevas versiones de una estructura.

Consulta la documentación oficial de Vavr y el repositorio del proyecto para ampliar los ejemplos.