https://github.com/mmnaseri/tuples4j
Fluent tuples for Java
https://github.com/mmnaseri/tuples4j
fp functional functional-programming functions java tuples
Last synced: 2 months ago
JSON representation
Fluent tuples for Java
- Host: GitHub
- URL: https://github.com/mmnaseri/tuples4j
- Owner: mmnaseri
- License: mit
- Created: 2020-04-28T23:41:35.000Z (almost 6 years ago)
- Default Branch: development
- Last Pushed: 2023-05-09T18:48:11.000Z (almost 3 years ago)
- Last Synced: 2025-07-12T03:13:20.386Z (8 months ago)
- Topics: fp, functional, functional-programming, functions, java, tuples
- Language: Java
- Size: 313 KB
- Stars: 2
- Watchers: 1
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# tuples4j
[](https://paypal.me/mmnaseri)
[](http://opensource.org/licenses/MIT)
[](https://maven-badges.herokuapp.com/maven-central/com.mmnaseri.utils/tuples4j)
[](https://travis-ci.org/mmnaseri/tuples4j)
[](https://www.codacy.com/manual/mmnaseri/tuples4j?utm_source=github.com&utm_medium=referral&utm_content=mmnaseri/tuples4j&utm_campaign=Badge_Grade)[](https://www.codefactor.io/repository/github/mmnaseri/tuples4j)
[](https://coveralls.io/github/mmnaseri/tuples4j)
---
A tiny library for working with [tuples](https://en.wikipedia.org/wiki/Tuple) as first-class citizens, in Java.
This library has been designed to play well with Java 8+'s collections and streams APIs and fits nicely into the
functional programming paradigm familiar to Java 8 developers.
This code is well tested, and is easy to parse.
## Getting Starting
To download the code and use it in your project, you can either clone this project and start using it:
$ git clone https://github.com/mmnaseri/tuples4j.git
or you can add a maven dependency since it is now available in Maven central:
com.mmnaseri.utils
tuples4j
${tuples4j.version}
To get started, use one of the many utility methods under the `Tuple` interface as the entrypoint:
```java
ThreeTuple t = Tuple.three(1, "x", true);
// Or, if you prefer to get rid of the type-safety mechanism:
Tuple> t = Tuple.three(1, "x", true);
```
Tuples are immutable, so, feel free to pass them around:
```java
// Create a bunch of one-tuples.
Set> tuples = Stream.of(Tuple.of(1), Tuple.of(2))
// Extend them each to two-tuples.
.map(Tuple.extendOne("Hello")) // this is the same as: .map(t -> t.extend("Hello"))
// Change the first element.
.map(t -> t.first(Objects::toString))
// Sort by the second element.
.sorted(Comparator.comparing(HasSecond::second))
// Collect them all as a set.
.collect(toSet());
```
## Features
### JDK 8-14 Compatible
This project is regular built against and tested with OpenJDK 8 - 14. Click on the build badge above to find out more.
### Tuple Sizes
This library offers a wide set of tuples, from size 0 (the *empty* tuple), to size 12 and beyond.
The build-in tuple sizes are:
* `EmptyTuple`,
* `OneTuple`,
* `TwoTuple`, also available as `Pair` and `KeyValue`,
* `ThreeTuple`,
* `FourTuple`,
* `FiveTuple`,
* `SixTuple`,
* `SevenTuple`,
* `EightTuple`,
* `NineTuple`,
* `TenTuple`,
* `ElevenTuple`,
* `TwelveTuple`.
Beyond these, there is the `ThirteenOrMoreTuple` class which holds data for thirteen or more elements.
### Type-safe Elements
All elements are bound to an individual type argument, meaning that you can carry that type information
and will not need to cast the items to the actual types.
Moreover, each tuple type has a tightly bound, generically defined constructor and factory method, that
can be used if you want to enforce an upperbound on the datatypes. For instance, to create a number-only
three-tuple, you can write:
```java
ThreeTuple tuple = ThreeTuple.of(1, 1.2D, 3L);
```
### `equals`, `hashCode()`, and `toString()`
All tuples have their own implementation of these three basic methods. These are also well-tested
and you can consult the tests for examples.
For instance:
```java
Tuple.of(1, 2, 3).equals(Tuple.of(1, 2, 3, "a").dropFourth()) // => true
```
### Labeled Tuples
Some applications might require access to datum by labels. In this case, you can easily label your
tuples like so:
```java
LabeledTuple> t = Tuple.of("USA", 3.2).withLabels("country", "population");
System.out.println(t.get("population")); // => 3.2
```
### Named Accessors
All tuples which have a fixed dimension, have facades that allow named interactions. For instance,
a four-tuple, would implement all the facades for `HasFirst`, `HasSecond`, `HasThird`, and `HasFourth`.
This means that to get the second element in the tuple, instead of writing `tuple.get(1)`, you can
write `tuple.second()`. This also applies to changing values on the tuples. Instead of calling
`tuple.change(2, "a")`, you can write `tuple.third("a")`. Not only is this syntax semantically
stronger, but also it can help preserve type arguments on the tuple itself.
## Reflective Access
The companion module `tuples4j-reflection` can be used to get tuples represented as classes:
```java
ReflectiveTuple> reflectiveTuple = ReflectiveTuple.of(tuple);
Customer customer = reflectiveTuple.as(Customer.class);
String name = customer.name();
BigDecimal income = customer.income();
```
You can do all sorts of customizations in how a value is read from the tuple and conveyed as a method's return value:
```java
public interface Customer {
String name();
BigDecimal income();
State state();
@Provided(by = IncomeBracketProvider.class)
IncomeBracket incomeBracket();
double raise();
default nextYearIncome() {
return income().multiply(raise());
}
enum State {
TX, WA, CA, OR
}
}
```
Look at [tuples4j-reflection/~/test/~/model/Country.java](https://github.com/mmnaseri/tuples4j/blob/master/tuples4j-reflection/src/test/java/com/mmnaseri/utils/tuples/model/Country.java) for a better example of the sort of things you can do with the reflective code.
### Using the Reflection Module
To use the reflection module, get yourself a copy by either cloning this project or using Maven:
com.mmnaseri.utils
tuples4j-reflection
${tuples4j.version}
## Building and Contributing
Contributions are more than welcome :)
To build the code and/or to contribute, you can use the provided `Dockerfile` image. This image sets up an Ubuntu Bionic (18.04 LTS) with OpenJDK 8. This is the minimum required environment for the project to work.
You can get a working Docker image by running:
```bash
docker build -t tuples4j:jdk8 .
docker run -it tuples4j:jdk8
```