mirror of
https://github.com/kestra-io/kestra.git
synced 2025-12-25 20:00:14 -05:00
Compare commits
1 Commits
plugin/tem
...
chore/util
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ca58283f9 |
176
core/src/main/java/io/kestra/core/utils/Pair.java
Normal file
176
core/src/main/java/io/kestra/core/utils/Pair.java
Normal file
@@ -0,0 +1,176 @@
|
||||
package io.kestra.core.utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* An immutable tuple of two elements.
|
||||
*
|
||||
* @param <T1> the type of the 1st element.
|
||||
* @param <T2> the type of the 2nd element.
|
||||
*/
|
||||
public record Pair<T1, T2>(T1 _1, T2 _2) {
|
||||
|
||||
/**
|
||||
* Creates a {@code Pair} from a Map.Entry.
|
||||
*
|
||||
* @param entry the Map.Entry to convert
|
||||
* @param <T1> the key type
|
||||
* @param <T2> the value type
|
||||
* @return a new Pair with the key and value from the entry
|
||||
*/
|
||||
public static <T1, T2> Pair<T1, T2> of(Map.Entry<T1, T2> entry) {
|
||||
return new Pair<>(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code Pair} from two values.
|
||||
*
|
||||
* @param o1 the first value
|
||||
* @param o2 the second value
|
||||
* @param <T1> the type of the first value
|
||||
* @param <T2> the type of the second value
|
||||
* @return a new Pair of the two values
|
||||
*/
|
||||
public static <T1, T2> Pair<T1, T2> of(T1 o1, T2 o2) {
|
||||
return new Pair<>(o1, o2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tuple of two elements.
|
||||
*
|
||||
* @param _1 the 1st element
|
||||
* @param _2 the 2nd element
|
||||
*/
|
||||
public Pair {
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link #_1()}.
|
||||
*
|
||||
* @return the first element
|
||||
*/
|
||||
public T1 key() {
|
||||
return this._1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link #_2()}.
|
||||
*
|
||||
* @return the second element
|
||||
*/
|
||||
public T2 value() {
|
||||
return this._2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link #_1()}.
|
||||
*
|
||||
* @return the first element
|
||||
*/
|
||||
public T1 left() {
|
||||
return this._1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link #_2()}.
|
||||
*
|
||||
* @return the second element
|
||||
*/
|
||||
public T2 right() {
|
||||
return this._2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the first element of the pair.
|
||||
*
|
||||
* @param mapper function to transform the first element
|
||||
* @param <R> the result type of the transformation
|
||||
* @return a new Pair with the transformed first element
|
||||
*/
|
||||
public <R> Pair<R, T2> mapLeft(Function<? super T1, ? extends R> mapper) {
|
||||
return new Pair<>(mapper.apply(_1), _2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the second element of the pair.
|
||||
*
|
||||
* @param mapper function to transform the second element
|
||||
* @param <R> the result type of the transformation
|
||||
* @return a new Pair with the transformed second element
|
||||
*/
|
||||
public <R> Pair<T1, R> mapRight(Function<? super T2, ? extends R> mapper) {
|
||||
return new Pair<>(_1, mapper.apply(_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms both elements of the pair.
|
||||
*
|
||||
* @param leftMapper function to transform the first element
|
||||
* @param rightMapper function to transform the second element
|
||||
* @param <R1> result type of first element
|
||||
* @param <R2> result type of second element
|
||||
* @return a new Pair with both elements transformed
|
||||
*/
|
||||
public <R1, R2> Pair<R1, R2> mapBoth(Function<? super T1, ? extends R1> leftMapper,
|
||||
Function<? super T2, ? extends R2> rightMapper) {
|
||||
return new Pair<>(leftMapper.apply(_1), rightMapper.apply(_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a bi-function to both elements.
|
||||
*
|
||||
* @param mapper function to apply to both elements
|
||||
* @param <R> result type
|
||||
* @return the result of applying the function to the pair
|
||||
*/
|
||||
public <R> R reduce(BiFunction<? super T1, ? super T2, ? extends R> mapper) {
|
||||
return mapper.apply(_1, _2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Stream} containing only this pair.
|
||||
*
|
||||
* @return a singleton stream of this pair
|
||||
*/
|
||||
public Stream<Pair<T1, T2>> stream() {
|
||||
return Stream.of(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this pair into a {@link Map.Entry}.
|
||||
*
|
||||
* @return a Map.Entry representing the pair
|
||||
*/
|
||||
public Map.Entry<T1, T2> asMapEntry() {
|
||||
return Map.entry(this._1, this._2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the elements of the pair.
|
||||
*
|
||||
* @return a new Pair with the elements swapped
|
||||
*/
|
||||
public Pair<T2, T1> swap() {
|
||||
return new Pair<>(_2, _1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if both elements are null.
|
||||
*
|
||||
* @return true if both elements are null
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return _1 == null && _2 == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + _1 + "," + _2 + ')';
|
||||
}
|
||||
}
|
||||
138
core/src/test/java/io/kestra/core/utils/PairTest.java
Normal file
138
core/src/test/java/io/kestra/core/utils/PairTest.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package io.kestra.core.utils;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.*;
|
||||
|
||||
class PairTest {
|
||||
|
||||
@Test
|
||||
void shouldCreatesPairGivenTwoValues() {
|
||||
// Given
|
||||
String key = "foo";
|
||||
Integer value = 123;
|
||||
|
||||
// When
|
||||
Pair<String, Integer> pair = Pair.of(key, value);
|
||||
|
||||
// Then
|
||||
assertThat(pair._1()).isEqualTo("foo");
|
||||
assertThat(pair._2()).isEqualTo(123);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreatesPairGivenMapEntry() {
|
||||
// Given
|
||||
Map.Entry<String, Integer> entry = new AbstractMap.SimpleEntry<>("bar", 42);
|
||||
|
||||
// When
|
||||
Pair<String, Integer> pair = Pair.of(entry);
|
||||
|
||||
// Then
|
||||
assertThat(pair.key()).isEqualTo("bar");
|
||||
assertThat(pair.value()).isEqualTo(42);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTransformsFirstElement() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("test", 10);
|
||||
|
||||
// When
|
||||
Pair<Integer, Integer> result = pair.mapLeft(String::length);
|
||||
|
||||
// Then
|
||||
assertThat(result._1()).isEqualTo(4);
|
||||
assertThat(result._2()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTransformsSecondElement() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("hello", 5);
|
||||
|
||||
// When
|
||||
Pair<String, String> result = pair.mapRight(Object::toString);
|
||||
|
||||
// Then
|
||||
assertThat(result._1()).isEqualTo("hello");
|
||||
assertThat(result._2()).isEqualTo("5");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSwapElements() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("left", 99);
|
||||
|
||||
// When
|
||||
Pair<Integer, String> swapped = pair.swap();
|
||||
|
||||
// Then
|
||||
assertThat(swapped._1()).isEqualTo(99);
|
||||
assertThat(swapped._2()).isEqualTo("left");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetStreamOfOneElement() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("stream", 1);
|
||||
|
||||
// When
|
||||
long count = pair.stream().count();
|
||||
|
||||
// Then
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetAsMapEntry() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("key", 888);
|
||||
|
||||
// When
|
||||
Map.Entry<String, Integer> entry = pair.asMapEntry();
|
||||
|
||||
// Then
|
||||
assertThat(entry.getKey()).isEqualTo("key");
|
||||
assertThat(entry.getValue()).isEqualTo(888);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCheckIfBothElementsAreNull() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of(null, null);
|
||||
|
||||
// When
|
||||
boolean isEmpty = pair.isEmpty();
|
||||
|
||||
// Then
|
||||
assertThat(isEmpty).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTransformsBothElements() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("abc", 7);
|
||||
|
||||
// When
|
||||
Pair<Integer, String> result = pair.mapBoth(String::length, Object::toString);
|
||||
|
||||
// Then
|
||||
assertThat(result).isEqualTo(Pair.of(3, "7"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReduceElements() {
|
||||
// Given
|
||||
Pair<String, Integer> pair = Pair.of("val", 2);
|
||||
|
||||
// When
|
||||
String result = pair.reduce((s, i) -> s + "-" + i);
|
||||
|
||||
// Then
|
||||
assertThat(result).isEqualTo("val-2");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user