import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StackBleed {
public static int check(String s) {
if (s.equals("lambda")) {
throw new IllegalArgumentException();
}
return s.length();
}
#SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
// List lengths = new ArrayList();
List<String> argList = Arrays.asList(args);
Stream lengths2 = argList.stream().map((String name) -> check(name));
}
}
So I was checking out this article http://www.takipiblog.com/2014/03/25/the-dark-side-of-lambda-expressions-in-java-8/ and wrote similar class, but JDK 8 approach didn't yield expected exception. I was wondering if they have changed something in JDK 8u5?
You're only calling a non-terminal operation on the stream. So your code doesn't consume the data from the stream. All it does is saying: "when a terminal operation will be called, you'll have to map the strings using the check() method".
Use
List<Integer> transformed =
argList.stream().map((String name) -> check(name)).collect(Collectors.toList());
for example, and then the call to collect(), which is a terminal operation, will trigger the iteration on the stream elements and the transformation of its elements.
Related
I have a list of Class1, which has a method isAvailable() which returns a boolean.
I am trying to create an array of boolean from this.
So far I have tried the below:
List<Class1> class1List;
boolean[] isAvailableArray = class1List.stream()
.map(e -> e.isAvailable())
.toArray();
However this is throwing a can't convert from Object[] to boolean[] error.
What is the reason for this.
As you can see in the following example, the stream handles the primitive boolean values correctly (it creates Boolean objects). However, when toArray is used without a generator param (constructor), it falls back to an Object array.
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class BooleanStream {
public static class SomeClass {
public boolean isAvailable() {
return true;
}
}
#Test
public void testBoolean() {
List<ByteArray.SomeClass> list = new ArrayList<>();
ByteArray.SomeClass someClass = new ByteArray.SomeClass();
list.add(someClass);
Object[] isAvailableArray = list.stream().map(e -> e.isAvailable()).toArray();
assertTrue(isAvailableArray[0] instanceof Boolean);
}
}
As experiment-unit-1998x pointed out, the best solution is probably the generator param.
I am trying to implement Parameterized test in which I have a set of input and expected values which I want to test using assertEquals method of JUnit. I'm using JUnit version 5.x for this I am passing the input value to my custom method defined in other package (that I'm testing) and I am checking it with an expected value with assertEquals method.
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.runners.Parameterized.Parameters;
class StringHelperTest {
private StringHelper helper = new StringHelper();
private String input;
private String expectedOutput;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getExpectedOutput() {
return expectedOutput;
}
public void setExpectedOutput(String expectedOutput) {
this.expectedOutput = expectedOutput;
}
#Parameters
public static Collection<String[]> testConditions() {
String[][] expectedOutputs = { { "AACD", "CD" }, { "ACD", "CD" }, { "CDEF", "CDEF" }, { "CDAA", "CDAA" } };
return Arrays.asList(expectedOutputs);
}
#ParameterizedTest
#Test
public void truncateAInFirst2Positions_A_atStart() {
assertEquals(expectedOutput, helper.truncateAInFirst2Positions(input));
}
}
In the method testConditions() the actual and expected values are given as a 2 dimensinonal String array expectedOutputs {{<actual_value>,<expected_value>},{...}}.
How do I pass expectedOutputs array to the truncateAInFirst2Positions_A_atStart() method to test all conditions mentioned in expectedOutputs array
With JUnit 5 you have ParameterizedTest and a Source for the input parameters, which are simple the parameters of the method.
So you want a Method with this signature:
#ParameterizedTest
//Source Annotation
void truncateAInFirst2Positions_A_atStart(String actual, String expected) {
And now you look up a for your use case matching source. When you want to proivde your test data with your method you could use #MethodSource("testConditions"). The String in the annotation points to the static method providing your test data. The test will be executed x times where x is the count of pairs in your collection. The elements in your String Array will be used as method arguments.
For simple types like Strings a CSV source can be simpler and easier to read:
#CsvSource({
"AACD, CD",
"ACD, CD"
})
You can check all possible sources and possiblites in the offcial documentation:
https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
Just for reference as the question is already answered, but if you need something else than strings (e.g. your own objects) you can use org.junit.jupiter.params.provider.Arguments.arguments, e.g.:
#ParameterizedTest
#MethodSource("provideMyObject")
void myTestMethod(ActualObject actual, ExpectedObject expected) {
// ...
}
static Stream<Arguments> provideMyObject() {
return Stream.of(
org.junit.jupiter.params.provider.Arguments.arguments(new ActualObject("foo"), new ExpectedObject("foo")),
org.junit.jupiter.params.provider.Arguments.arguments(new ActualObject("bar"), new ExpectedObject("bar))
);
}
see also: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests-sources-MethodSource
when running this code snippet. Is there any noticeable difference in performance or something else to take into consideration when choosing between a lambda, a method reference or a method with a Function as return value?
import java.util.function.Function;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream<String> firstStream = Stream.of("qwerty", "asdfgh", "zxcvbn")
.map(s -> s.concat(s));
Stream<String> secondStream = Stream.of("qwerty", "asdfgh", "zxcvbn")
.map(Main::selfConcatenateReference);
Stream<String> thirdStream = Stream.of("qwerty", "asdfgh", "zxcvbn")
.map(selfConcatenateFunction());
}
private static Function<String, String> selfConcatenateFunction() {
return s -> s.concat(s);
}
private static String selfConcatenateReference(String s) {
return s.concat(s);
}
}
I got an error when I tried to test 2 ArraysLists.
It seems the error is saying "toArray() is undefined" at my removeEndWith_at method. Could you guys give me an advice how to test these 2 ArraysList?
Thanks.
Java version: jdk-10.0.2
JUnit:5
[ArrayListIterator Class]
import java.util.Iterator;
import java.util.List;
public class ArrayListIterator {
/**
* #param wordsAl : list of words
*/
public List<String> removeEndWith_at(List<String> wordsAl) {
Iterator<String> iterator = wordsAl.iterator();
while (iterator.hasNext()) {
if (iterator.next().endsWith("at"))
iterator.remove();
}
return wordsAl;
}
}
[ArrayListIteratorTest Class]
import static org.junit.Assert.assertArrayEquals;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Test;
class ArrayListIteratorTest {
ArrayListIterator alIterator = new ArrayListIterator();
List<String> actualWords = Arrays.asList("Apple", "Bat", "Orange", "Cat");
#Test
void testremoveEndWith_at() {
actualWords = alIterator.removeEndWith_at(actualWords);
List<String> expectedvalue = Arrays.asList("Apple", "Orange");
assertArrayEquals(expectedvalue.toArray(), actualWords.toArray());
}
}
Look at the
remove() on List created by Arrays.asList() throws UnsupportedOperationException
Arrays.asList()
method just creates a wrapper around the original elements and on this wrapper are not implemented methods which changes its size.
Also look at my implementation of method removeEndWith_at. It is simpler than yours version
/**
* #param wordsAl : list of words
*/
public List<String> removeEndWith_at(List<String> wordsAl) {
wordsAl.removeIf(s -> s.endsWith("at"));
return wordsAl;
}
When comparing two instances of List<String> using Jupiter Assertion API, give assertLinesMatch a try.
Getting my feet wet on RxJava. I have a class that implements Iterable I want to convert to an Observable. Using Observable.from() seems easy. However I need to setup and tear-down the code that provides me the individual entries (the next() in the iterator.
When I run through the entire sequence, that's easy. I added the call to the hasNext() function and when there is no next I run the teardown. However one of the very promising operators I want to use is take(someNumber). If the taking stops before the Iterator runs out of items, the cleanup code never runs.
What can I do to get my cleanup running? If using something else than from(Iterable), I'm OK with that. I'm stuck on Java6 for now. To illustrate my predicament I created a minimal sample:
Update: Based on feedback not to mix Iterator and Iterable together, I updated the code below. To understand the original answers, the original code is in that gist.
Updated Test code (still bad):
import rx.Observable;
import rx.functions.Action0;
import rx.functions.Action1;
/**
* #author stw
*
*/
public class RXTest {
/**
* #param args
*/
public static void main(String[] args) {
ComplicatedObject co = new ComplicatedObject();
Observable<FancyObject> fancy = Observable.from(co);
// if the take is less than the elements cleanup never
// runs. If you take the take out, cleanup runs
fancy.take(3).subscribe(
new Action1<FancyObject>() {
public void call(FancyObject item) {
System.out.println(item.getName());
}
},
new Action1<Throwable>() {
public void call(Throwable error) {
System.out.println("Error encountered: " + error.getMessage());
}
},
new Action0() {
public void call() {
System.out.println("Sequence complete");
}
}
);
}
}
The fancy object:
import java.util.Date;
import java.util.UUID;
/**
* #author stw
*
*/
public class FancyObject {
private String name = UUID.randomUUID().toString();
private Date created = new Date();
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return this.created;
}
public void setCreated(Date created) {
this.created = created;
}
}
The iterator:
import java.util.Iterator;
/**
* #author stw
*
*/
public class FancyIterator implements Iterator<FancyObject> {
private final ComplicatedObject theObject;
private int fancyCount = 0;
public FancyIterator(ComplicatedObject co) {
this.theObject = co;
}
public boolean hasNext() {
return this.theObject.hasObject(this.fancyCount);
}
public FancyObject next() {
FancyObject result = this.theObject.getOne(this.fancyCount);
this.fancyCount++;
return result;
}
}
The Iterable:
import java.util.Iterator;
import java.util.Vector;
/**
* #author stw
*
*/
public class ComplicatedObject implements Iterable<FancyObject> {
private boolean isInitialized = false;
Vector<FancyObject> allOfThem = new Vector<FancyObject>();
public Iterator<FancyObject> iterator() {
return new FancyIterator(this);
}
public boolean hasObject(int whichone) {
if (!this.isInitialized) {
this.setupAccesstoFancyObject();
}
return (whichone < this.allOfThem.size());
}
public FancyObject getOne(int whichone) {
if (!this.isInitialized) {
this.setupAccesstoFancyObject();
}
if (whichone < this.allOfThem.size()) {
return this.allOfThem.get(whichone);
}
// If we ask bejond...
this.isInitialized = false;
this.teardownAccessToFancyObjects();
return null;
}
private void setupAccesstoFancyObject() {
System.out.println("Initializing fancy objects");
for (int i = 0; i < 20; i++) {
this.allOfThem.addElement(new FancyObject());
}
this.isInitialized = true;
}
private void teardownAccessToFancyObjects() {
System.out.println("I'm doing proper cleanup here");
}
}
But the real question (thx #Andreas) seem to be:
What construct can I use to create an Observable when the underlying code need setup/teardown, especially when one expects that not all elements are pulled. The Iterable just was my first idea
Update 2: Based on Dave's answer I created a gist with my working solution. The iterator isn't perfect, but it's a start.
Observable.using is used for tearing down on termination (completion or error) or unsubscription. To use it you need to make the tear-down code accessible so that your source observable can look like this:
source = Observable.using(
resourceFactory,
observableFactory,
resourceDisposer);
With your code it might look like this:
source = Observable.using(
() -> new ComplicatedObject(),
co -> Observable.from(co),
co -> co.tearDown());
If you want that kind of control you need to separate the implementation of Iterable from Iterator. Iterable means the class can provide an Iterator that is meaningful in whatever fashion makes sense for the class.
However, if you implement Iterator in the same class, then you are stuck with only ever having one Iterator for each instance of ComplicatedObject. The correct approach is to implement
class FancyObjectIterator implements Iterator<FancyObject>
{
...
}
separately from ComplicatedObject so you can merely discard the partially-used iterators when you are done with them. ComplicatedObject should implement only Iterable<FancyObject>.
If you object to that approach because the iterator has more state that needs special cleanup, then something is wrong with your design. The only state an Iterator should be aware of is the current position in the base "collection", for a very loose definition of "collection" and "position" since the concept of an iterator can apply to much more than typical collections.
You cannot implement Iterator and Iterable at the same time, since Iterable.iterator() must return a new Iterator or every call.
Code is allowed to iterate the same Iterable multiple times in parallel.
Example: An over-simplified way to find duplicate elements in an Iterable:
Iterable<MyObject> myIterable = ...;
for (MyObject myObj1 : myIterable) {
for (MyObject myObj2 : myIterable) {
if (myObj1 != myObj2 && myObj1.equals(myObj2)) {
// found duplicate
}
}
}
The enhanced for loops used here will each use an Iterator.
As you can see, each Iterator must maintain it's own independent position. Therefore, the iterator() method needs to return a new object, with it's own state.
And for your question on cleanup code, an Iterator does not have a close() method. Iterator state should not require cleanup. If they absolutely must, a finalizer can do it, but finalizers may take a very long time to be invoked. The general recommendation for finalizers is: DON'T.