Git Product home page Git Product logo

cactoos's Introduction

logo

EO principles respected here DevOps By Rultor.com We recommend IntelliJ IDEA

mvn Javadoc PDD status Maven Central License Test Coverage SonarQube Hits-of-Code Codacy Badge

Project architect: @victornoel

ATTENTION: We're still in a very early alpha version, the API may and will change frequently. Please, use it at your own risk, until we release version 1.0. You can view our progress towards this release here.

Cactoos is a collection of object-oriented Java primitives.

Motivation. We are not happy with JDK, Guava, and Apache Commons because they are procedural and not object-oriented. They do their job, but mostly through static methods. Cactoos is suggesting to do almost exactly the same, but through objects.

Principles. These are the design principles behind Cactoos.

How to use. The library has no dependencies. All you need is this (get the latest version here):

Maven:

<dependency>
  <groupId>org.cactoos</groupId>
  <artifactId>cactoos</artifactId>
  <version>0.55.0</version>
</dependency>

Gradle:

dependencies {
  compile 'org.cactoos:cactoos::0.55.0
}

Java version required: 1.8+.

StackOverflow tag is cactoos.

Input/Output

More about it here: Object-Oriented Declarative Input/Output in Cactoos.

To read a text file in UTF-8:

String text = new TextOf(
  new File("/code/a.txt")
).asString();

To write a text into a file:

new LengthOf(
  new TeeInput(
    "Hello, world!",
    new File("/code/a.txt")
  )
).value();

To read a binary file from classpath:

byte[] data = new BytesOf(
  new ResourceOf("foo/img.jpg")
).asBytes();

Text/Strings

To format a text:

String text = new FormattedText(
  "How are you, %s?",
  name
).asString();

To manipulate with a text:

// To lower case
new Lowered(
	new TextOf("Hello")
);
// To upper case
new Upper(
	new TextOf("Hello")
);

Iterables/Collections/Lists/Sets

More about it here: Lazy Loading and Caching via Sticky Cactoos Primitives.

To filter a collection:

Collection<String> filtered = new ListOf<>(
  new Filtered<>(
    s -> s.length() > 4,
    new IterableOf<>("hello", "world", "dude")
  )
);

To flatten one iterable:

new Joined<>(
  new Mapped<IterableOf>(
    iter -> new IterableOf<>(
      new ListOf<>(iter).toArray(new Integer[]{})
    ),
    new IterableOf<>(1, 2, 3, 4, 5, 6)
  )
);    // Iterable<Integer>

To flatten and join several iterables:

new Joined<>(
  new Mapped<IterableOf>(
    iter -> new IterableOf<>(
      new Joined<>(iter)
    ),
    new Joined<>(
      new IterableOf<>(new IterableOf<>(1, 2, 3)),
      new IterableOf<>(new IterableOf<>(4, 5, 6))
    )
  )
);    // Iterable<Integer>

To iterate a collection:

new And(
  new Mapped<>(
    new FuncOf<>(
      input -> {
        System.out.printf("Item: %s\n", input);
      },
      new True()
    ),
    new IterableOf<>("how", "are", "you", "?")
  )
).value();

Or even more compact:

new ForEach<String>(
    input -> System.out.printf(
        "Item: %s\n", input
    )
).exec(new IterableOf("how", "are", "you", "?"));

To sort a list of words in the file:

List<Text> sorted = new ListOf<>(
  new Sorted<>(
    new Mapped<>(
      text -> new ComparableText(text),
      new Split(
        new TextOf(
          new File("/tmp/names.txt")
        ),
        new TextOf("\\s+")
      )
    )
  )
);

To count elements in an iterable:

int total = new LengthOf(
  new IterableOf<>("how", "are", "you")
).value().intValue();

To create a set of elements by providing variable arguments:

final Set<String> unique = new SetOf<String>(
    "one",
    "two",
    "one",
    "three"
);

To create a set of elements from existing iterable:

final Set<String> words = new SetOf<>(
    new IterableOf<>("abc", "bcd", "abc", "ccc")
);

To create a sorted iterable with unique elements from existing iterable:

final Iterable<String> sorted = new Sorted<>(
    new SetOf<>(
        new IterableOf<>("abc", "bcd", "abc", "ccc")
    )
);

To create a sorted set from existing vararg elements using comparator:

final Set<String> sorted = new org.cactoos.set.Sorted<>(
    (first, second) -> first.compareTo(second),
    "abc", "bcd", "abc", "ccc", "acd"
);

To create a sorted set from existing iterable using comparator:

final Set<String> sorted = new org.cactoos.set.Sorted<>(
    (first, second) -> first.compareTo(second),
    new IterableOf<>("abc", "bcd", "abc", "ccc", "acd")
);

Funcs and Procs

This is a traditional foreach loop:

for (String name : names) {
  System.out.printf("Hello, %s!\n", name);
}

This is its object-oriented alternative (no streams!):

new And(
  n -> {
    System.out.printf("Hello, %s!\n", n);
    return new True().value();
  },
  names
).value();

This is an endless while/do loop:

while (!ready) {
  System.out.println("Still waiting...");
}

Here is its object-oriented alternative:

new And(
  ready -> {
    System.out.println("Still waiting...");
    return !ready;
  },
  new Endless<>(booleanParameter)
).value();

Dates and Times

From our org.cactoos.time package.

Our classes are divided in two groups: those that parse strings into date/time objects, and those that format those objects into strings.

For example, this is the traditional way of parsing a string into an OffsetDateTime:

final OffsetDateTime date = OffsetDateTime.parse("2007-12-03T10:15:30+01:00");

Here is its object-oriented alternative (no static method calls!) using OffsetDateTimeOf, which is a Scalar:

final OffsetDateTime date = new OffsetDateTimeOf("2007-12-03T10:15:30+01:00").value();

To format an OffsetDateTime into a Text:

final OffsetDateTime date = ...;
final String text = new TextOfDateTime(date).asString();

Our objects vs. their static methods

Cactoos Guava Apache Commons JDK 8
And Iterables.all() - -
Filtered Iterables.filter() ? -
FormattedText - - String.format()
IsBlank - StringUtils.isBlank() -
Joined - - String.join()
LengthOf - - String#length()
Lowered - - String#toLowerCase()
Normalized - StringUtils.normalize() -
Or Iterables.any() - -
Repeated - StringUtils.repeat() -
Replaced - - String#replace()
Reversed - - StringBuilder#reverse()
Rotated - StringUtils.rotate() -
Split - - String#split()
StickyList Lists.newArrayList() ? Arrays.asList()
Sub - - String#substring()
SwappedCase - StringUtils.swapCase() -
TextOf ? IOUtils.toString() -
TrimmedLeft - StringUtils.stripStart() -
TrimmedRight - StringUtils.stripEnd() -
Trimmed - StringUtils.stripAll() String#trim()
Upper - - String#toUpperCase()

Questions

Ask your questions related to cactoos library on Stackoverflow with cactoos tag.

How to contribute?

Just fork the repo and send us a pull request.

Make sure your branch builds without any warnings/issues:

mvn clean verify -Pqulice

To run a build similar to the CI with Docker only, use:

docker run \
	--tty \
	--interactive \
	--workdir=/main \
	--volume=${PWD}:/main \
	--volume=cactoos-mvn-cache:/root/.m2 \
	--rm \
	maven:3-jdk-8 \
	bash -c "mvn clean install site -Pqulice -Psite --errors; chown -R $(id -u):$(id -g) target/"

To remove the cache used by Docker-based build:

docker volume rm cactoos-mvn-cache

Note: Checkstyle is used as a static code analyze tool with checks list in GitHub precommits.

Contributors

cactoos's People

Contributors

akryvtsun avatar alex-semenyuk avatar andreoss avatar bedward70 avatar dgroup avatar dmitrybarskov avatar fabriciofx avatar fanifieiev avatar g4s8 avatar iakunin avatar ilyakharlamov avatar ixmanuel avatar kokodyn avatar krzyk avatar llorllale avatar longstone avatar marceloamadeu avatar paulodamaso avatar proshin-roman avatar renovate[bot] avatar rexim avatar rocket-3 avatar rultor avatar sharpler avatar svendiedrichsen avatar umbrah avatar victornoel avatar vssekorin avatar yegor256 avatar zefick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cactoos's Issues

UrlAsString and StringAsUrl

Let's create two new classes, which will replace URLEncoder and URLDecoder from JDK. We will still use JDK, but these wrappers will be very helpful. At least they won't throw checked exceptions.

Minimal Java version for the library

What java version is the library based?
In pom.xml I see

<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>

Does it mean the library isn't support java version less then 8?
If yes, why Func interface was introduced than reuse java.util.function.Function? Is it possible to use Java 8 streams in the library class implementations?

UncheckedScalar

Let's create UncheckedScalar, UncheckedText, and UncheckedBytes. Similar to UncheckedFunc

Not null text.

@yegor256 can I create pull request with NotNullText? Or is it redundant?
new UpperText(new StringAsText(null)).asString();
new UpperText(new NotNullText(new StringAsText(null))).asString();

Function result

Let's introduce new class Result (lazy evaluation). This class is necessary for #43.

TextAsBytes

Let's introduce new class TextAsBytes, together with test. This will help add a test #14

Predicate

Let's introduce new interface Pred (extends Func<X, Boolean>) that could be used to FilteredIterable, for example. This will add declarativeness and readability.

LengthOfIterator asValue() must not be called twice

LengthOfIterable.asValue() can only be called once.
Subsequent calls will just return 0.

Reproduce:
Create an Instance of LengthOfIterator
Call asValue() twice and compare both results to see the results are different

Expected:
Both results be the same.

Test Code:

@Test
public void immuatableLength() {
  LengthOfIterator length = new LengthOfIterator(
    new ArrayAsIterable<String>("muh", "kuh").iterator()
  );
  MatcherAssert.assertThat("Iterator length should not change because of a call to asValue",
                                 length.asValue() == length.asValue());
}

Code in ctors

In some ctors we have method calls for JDK's standard static methods. E.g.
https://github.com/yegor256/cactoos/pull/22/files#diff-537f42dacf5c41ee51d8dc12c8560ce5R51
or
https://github.com/yegor256/cactoos/pull/22/files#diff-537f42dacf5c41ee51d8dc12c8560ce5R73
Also look on ctors in
https://github.com/yegor256/cactoos/blob/master/src/main/java/org/cactoos/text/FormattedText.java
in master branch.

Sometimes we even have some non static JDK calls. E.g.
#20 (diff)

Question: have we avoid all of such method calls at all? So, literally,

Only new calls are available in ctors

rule everywhere?

It yes, have we avoid usage standard Arrays.asList and Collections.unmodifiableSet and create substitute for them?

Interaction with JDK entities

Cactoos intention, AFAIU, is to be a library (not a framework). So we have an issue with standard JDK entities interaction (strings, java statements, JDK functions etc.)

Here are 2 points: consuming some JDK entity and producing an entity to JDK.

The way for entity consuming shows StringAsText.java adapter. It adapts java.lang.String into org.cactoos.Text. So if we wanna use org.cactoos.text.UpperText we have to write

new UpperText(new StringAsText("java string"))

The way for producing shows Scalar.java interface with it's asValue method. E.g. LengthOfIterable implements Scalar<Integer> and should be used as

int length = new LengthOfIterable(...).asValue();

or

if (new IsBlank(new StringAsText("java string")).asValue()) {
...
}

For me the both producing and consuming look a bit cumbersome and verbose. Is there any way to make JDK interaction smoothly?

E.g. java.lang.CharSequence interface might be used instead of org.cactoos.Text and then string consuming might be looks like

new UpperText("some java literal")

as java.lang.String already implements java.lang.CharSequence interface.

Also, java.lang.Number can be used as superclass of scalar values. However, instead of CharSequence interface Number is an abstract class and, thus, less helpful.

WDYT?

Extract TeeInput.Stream class from TeeInput

@yegor256 Usually, I don't like classes big classes and private methods, classes and constants. Why? Because without them, our classes are smaller and more cohesive. So, to achieve this goal, I suggest extract the TeeInput.Stream class to a public TeeInputStream class.

What do you think?

Some predicates.

Let's introduce predicates:
Neg (Negative)
LogConj (Logical conjunction) with iterable
LogDisj (Logical disjunction) with iterable
and may be
True
False

This will allow you to use complex conditions.

AllOf, AnyOf

Let's create two new classes, all implementing Scalar<Boolean>

Proc

Let's create a new interface Proc

FuncAsIterator

Let's build a FuncAsIterator.

Example, you want an Endless Iterator/Iterable of PrimeNumbers. You would do (pseudocode)

new Iterable(
   new Iterator(
      new PrimeFunc()
   )
);

What should be the API of such a construct?

Should the Function that provides the next value take the last value as input, so the iterator would hold some state? Or should we have something new like a Provider that does not take input and hold his own state?

Once we get the API clear, i would like to contribute this.

Ternary

Let's introduce new class Ternary. This will help in issue #36, for example.

Apache Commons StringUtils analog implementation

Apache Commons has org.apache.commons.lang.StringUtils class with a set of helpful string static functions.

How such functions should be implemented in Cactoos? I see some approaches

  1. each of static functions has to be as a separate class. E.g. for StringUtils#isBlank new class BlankText should be implemented with only one method boolean is(). The development of this idea is introducing predicate interface.
  2. The same idea with BlankText class but it has to implement BooleanStatement or Binary interface with the single method boolean asBoolean()
  3. such helpful functions should be put into Text interface definition. Thus we can speak about smart java String analog implementation.

I don't like all of these approaches but the example is practical.

WDYT?

Qulice code checks are unclear

@yegor256 please, share somewhere Qulice static code rules (preferable in README.md file).
For me such errors are cryptic (at lease the first one)

[INFO] Checkstyle: src/main/java/org/cactoos/text/BlankText.java[63]: Using '++' is not allowed. (IllegalTokenCheck)
[INFO] Checkstyle: src/test/java/org/cactoos/text/BlankTextTest.java[47]: Indentation (20) must be same or less than previous line (12), or bigger by exactly 4 (CascadeIndentationCheck)
[INFO] Checkstyle: src/test/java/org/cactoos/text/BlankTextTest.java[61]: Indentation (20) must be same or less than previous line (12), or bigger by exactly 4 (CascadeIndentationCheck)
[INFO] Checkstyle: src/test/java/org/cactoos/text/BlankTextTest.java[75]: Indentation (20) must be same or less than previous line (12), or bigger by exactly 4 (CascadeIndentationCheck)

Drop takes framework dependency

In README.md we can read:

How to use. The library has no dependencies. All you need is this (get the latest version here):

So, cactoos depends on takes framework (in pom.xml and UrlAsInputTest.java) and this dependency should be removed.

Rename open() method in Input interface

@yegor256 According to EO Vol. 1, page 53:

I call a manipulator a method that makes modifications to the real-world entity being abstracted by an object. It always returns void, and its names are always verbs.

So my sugestion is change the method's name from open() to stream(). I think it makes sense, because the method is returning an InputStream.

What do you think?

Exceptions are not composable

I like how code examples look declarative. But there is a hidden issue with exceptions. Exceptions are goto statements to error handling block which is not composable and not object oriented.

The library does not give a way to declare how to handle errors. In some cases, it is good to terminate whole computation as soon as error occur, but other need some error handler that produces default value in place of failure.

This code will fail with IllegalStateException if there is an IO problem with any file.

List<String> linesFromFiles = 
new IterableAsList(
    new ConcatenatedIterable(
        new TransformedIterable<>(
            new ArrayAsIterable<>("/tmp/a.txt", "/tmp/b.txt", "/tmp/c.txt"),
            fileName ->
                new TextAsLines(
                    new InputAsText(
                        new FileAsInput(
                            new File(fileName)
                        )
                    )
                )
        )
    )
);

In order to change error handling strategy, in this specific example, I will need to write my custom implementation of InputAsText that instead of throwing exception produce some default text. This approach is not scalable because it requires reimplementing every class that can throw an exception.

FP languages have a way to declare a function that produces either result or error without throwing exceptions using interface Either<ERROR, RESULT>.

What approach cactoos user should use for custom error handling?

FilteredIterator remove() removes wrong element from underlying Iterator

Under certain circumstances, remove() on a FilteredIterator removes the wrong element from the underlying iterator.

Reproduce:
Create List containing 0,1,2,3. (0,1,2,3)
Retrieve FilteredIterator over this List, set input-> true as filter function (no real filtering)
Retrieve first element (0).
Call hasNext() on FilteredIterator
call remove() on FilteredIterator
Expected: Check original List, it should not contain 0 anymore, but still have 1 in it. (1,2,3)
Actual: List does not contain 1 anymore (0,2,3)

I forked this repo and wrote a quick unit test to showcase this bug.
The unittest unfortunately does not follow single statement unit test since i don't know how to reproduce a multi-stage bug within a single statement.

What happens here is remove() Removes from the underlying collection the last element returned by this iterator (optional operation).
Since hasNext() on the FilteredIterator already calls next() on the underlying iterator. Because of that, the next-pointers" in the underlying and the filtered iterator diverge.
Therefore a subsequent remove() will call remove() on the underlying iterator, which already has returned the next element.
But since the next() was not called yet on the filteredIterator this behaviour is unexpected.

I tried to come up with a solution, but since the filter operation needs to look ahead in the underlying operator, i cannot see a way to offer the remove() operation. But luckily the remove() operation is an optional operation, we can just remove it. For that is opened a PR.

Tl;dR
FilteredIterator next pointer diverge from the underlying Iterators next pointer. Therefore the remove-method does not work as expected.
UnitTest here

PR which makes remove() a not supported operation here #83

ThrowableAsText

Let's add a class, which will do what ExceptionUtils do in Apache Commons.

IterableAsList.java:56-58: Needs cached `LengthOfIterable`...

The puzzle 39-e7c34bd5 in src/main/java/org/cactoos/list/IterableAsList.java (lines 56-58) has to be resolved: "Needs cached LengthOfIterable version to improve IterableAsList performance. Now each call to size() goes through all iterable to calculate the size."

The puzzle was created by g4s8 on 27-May-17.

Estimate: 30 minutes, role: IMP.

If you have any technical questions, don't ask me, submit new tickets instead. The task will be "done" when the problem is fixed and the text of the puzzle is removed from the source code. Here is more about PDD and
about me.

FuncWithFallback

Let's create a class that will be a Func, but in case an exception is thrown, it will try to call a fallback Func:

new FuncWithCallback<Integer, String>(
  i -> {
    if (i > 10) {
      throw new Exception("Too much!");
    }
    return "Success";
  },
  ex -> {
    System.out.printf("We just failed: %s", ex.getMessage());
    return "Never mind";
  }
)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.