Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

USearch for Java

Installation

Installation via Maven Central is not supported due to Continuous Delivery complexity and poor support for native builds. Gradle installation is the recommended approach. For the most up-to-date version, the following Groovy script will download a "fat JAR" containing builds for Linux, Windows, macOS, and Android, compatible with all common hardware platforms:

repositories {
    mavenCentral()
    
    // Custom repository for USearch JAR
    flatDir {
        dirs 'lib'
    }
}

// Task to download USearch JAR from GitHub releases
task downloadUSearchJar {
    doLast {
        def usearchVersion = '2.24.0'
        def usearchUrl = "https://github.com/unum-cloud/usearch/releases/download/v${usearchVersion}/usearch-${usearchVersion}.jar"
        def usearchFile = file("lib/usearch-${usearchVersion}.jar")
        
        usearchFile.parentFile.mkdirs()
        if (!usearchFile.exists()) {
            new URL(usearchUrl).withInputStream { i ->
                usearchFile.withOutputStream { it << i }
            }
            println "Downloaded USearch JAR: ${usearchFile.name}"
        }
    }
}

// Make compilation depend on downloading USearch
compileJava.dependsOn downloadUSearchJar

dependencies {
    // USearch JAR from local lib directory (downloaded automatically)
    implementation name: 'usearch', version: '2.24.0', ext: 'jar'
}

Quickstart

import cloud.unum.usearch.Index;

public class Main {
    public static void main(String[] args) {
        try (Index index = new Index.Config()
                .metric(Index.Metric.COSINE)              // Or "cos"
                .quantization(Index.Quantization.FLOAT32) // Or "f32"
                .dimensions(3)
                .capacity(100)
                .build()) {
            
            // Add to Index
            float[] vector = {0.1f, 0.2f, 0.3f};
            index.add(42L, vector);

            // Search
            long[] keys = index.search(new float[]{0.1f, 0.2f, 0.3f}, 10);
            for (long key : keys) {
                System.out.println("Found key: " + key);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Serialization

To save and load the index from disk, use the following methods:

index.save("index.usearch");
index.load("index.usearch");
index.view("index.usearch");

Extracting, Updating, and Removing Values

It is generally not recommended to use HNSW indexes in case of frequent removals or major distribution shifts. For small updates, you can use the following methods:

float[] vector = index.get(42L);
boolean removed = index.remove(42L);
boolean renamed = index.rename(43L, 42L);

To obtain metadata:

long size = index.size();
long capacity = index.capacity();
long dimensions = index.dimensions();
long connectivity = index.connectivity();

Multiple Data Types and Quantization

USearch supports hardware-agnostic f64, f32, and i8 quantization for memory efficiency and performance optimization.

// Double precision (f64) for highest accuracy
try (Index doubleIndex = new Index.Config()
        .metric("cos")
        .dimensions(3)
        .quantization("f64")
        .build()) {
    
    double[] vector = {0.1, 0.2, 0.3};
    doubleIndex.add(42L, vector);
    
    double[] buffer = new double[3];
    doubleIndex.getInto(42L, buffer); // Memory-efficient retrieval
}

// Byte precision (i8) for memory efficiency  
try (Index byteIndex = new Index.Config()
        .metric("cos")
        .dimensions(3)
        .quantization("i8")
        .build()) {
    
    byte[] vector = {10, 20, 30};
    byteIndex.add(42L, vector);
    
    byte[] buffer = new byte[3];
    byteIndex.getInto(42L, buffer); // Memory-efficient retrieval
}

Batch Operations

USearch automatically detects batch operations when vector arrays contain multiple concatenated vectors:

try (Index index = new Index.Config()
        .metric("cos")
        .dimensions(2)
        .build()) {
    
    // Batch add: 3 vectors in one call
    float[] batchVectors = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
    index.add(100L, batchVectors); // Adds vectors at keys 100, 101, 102
    
    // Verify batch was added correctly
    System.out.println("Index size: " + index.size()); // Output: 3
}

Concurrent Operations

The USearch index is thread-safe and supports high-performance concurrent operations:

import java.util.concurrent.*;

try (Index index = new Index.Config()
        .metric("cos")
        .dimensions(4)
        .capacity(10000)
        .build()) {
    
    ExecutorService executor = Executors.newFixedThreadPool(8);
    
    // Concurrent additions from multiple threads
    CompletableFuture<Void>[] addTasks = new CompletableFuture[4];
    for (int t = 0; t < 4; t++) {
        final int threadId = t;
        addTasks[t] = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 1000; i++) {
                long key = threadId * 1000L + i;
                float[] vector = generateRandomVector(4);
                index.add(key, vector);
            }
        }, executor);
    }
    
    // Concurrent searches while adding
    CompletableFuture<Void>[] searchTasks = new CompletableFuture[4];
    for (int t = 0; t < 4; t++) {
        searchTasks[t] = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 100; i++) {
                float[] query = generateRandomVector(4);
                long[] results = index.search(query, 10);
                processResults(results);
            }
        }, executor);
    }
    
    // Wait for all operations to complete
    CompletableFuture.allOf(addTasks).join();
    CompletableFuture.allOf(searchTasks).join();
    executor.shutdown();
    
    System.out.println("Final index size: " + index.size());
}

private static float[] generateRandomVector(int dimensions) {
    float[] vector = new float[dimensions];
    for (int i = 0; i < dimensions; i++) {
        vector[i] = (float) Math.random();
    }
    return vector;
}