I have been trying to solve this problem with my code but it keeps throwing a NoSuchMethodException no matter what I do. Does this have to do with imports I have added?
The code is:
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.stream.LongStream;
public class Dishouse {
public Function<Long, Long> dionym() {
Function<Long, Long> meth = (a) -> a - 62;
return meth;
}
public Function<Float, Float> femality(Function<Float, Float> sorbonist) {
Function<Float, Float> func = (a) -> a / 92;
return func.compose(sorbonist);
}
public Optional<Long> bristler(LongStream s, Predicate<Long> p,
BinaryOperator<Long> b) {
LongStream result = s.filter((LongPredicate) p);
Long count = result.count();
long stre[] = result.toArray();
if (count > 1) {
Optional<Long> e = null;
for (int i = 0; i < stre.length; i++) {
e = Optional.of(b.apply(stre[i], stre[i + 1]));
}
return e;
} else {
return Optional.empty();
}
}
The error is:
Method bristler not found: java.lang.NoSuchMethodException: Dishouse.bristler(java.util.stream.Stream, java.util.function.Predicate, java.util.function.BinaryOperator)
Above, I have included the whole class Dishouse and no other class or method interacts with this class.
It doesn't. LongStream isn't a Stream. Possibly you want Stream<Long> instead, which is not the same thing (one operates on primitive longs, the other operates on Long objects).
For the same reason, casting a Predicate<Long> to LongPredicate cannot work. casts just assert types, they don't convert things (unless casting to one primitive to another primitive type), and a Predicate<Long> isn't a LongPredicate.
NB: Your code can also return either null or Optional.empty or some optional which is a gigantic code smell. This isn't how you are supposed to use optional.
LongStream is not a sub-interface of Stream. To map a Stream<Long> to a LongStream, use the following:
Stream<Long> sl = ...
LongStream ls = sl.mapToLong(x -> x);
Related
I have a class that has 3 properties, all with the same data type, let's say:
Class Test {
int i;
int j;
int k;
}
Then, I have a stream containing test classes (assume all the properties are notnull random integers):
Stream<Test> originalStream = Stream.of(test1,test2,test3);
How can I convert (or map?) that stream to a stream, made up by integers of the class.
Printing now the stream would look like this (printing is not the point, I just used it to illustrate how it should be structured):
{test1,test2,test3}
But what I want is for it to look like this:
{test1.i, test1.j, test1.k, test2.i, test2.j, test2.k, test3.i, test3.j, test3.k}
I know I probably didn't use the correct terminology (instance, object etc.), but I hope my question is clear.
This might be what you're looking for...
package streams;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
public class IntegersToStream {
public static void main(String[] args) {
(new IntegersToStream()).run();
}
public void run() {
Test test = new Test(1, 2, 3);
List<Test> tests = new ArrayList<>();
tests.add(test);
IntStream intStream = tests.stream()
.flatMapToInt(t -> IntStream.of(t.getI(), t.getJ(), t.getK()));
intStream.forEach(System.out::println);
}
public class Test {
int i;
int j;
int k;
public Test(int i, int j, int k) {
this.i = i;
this.j = j;
this.k = k;
}
public int getI() {
return i;
}
public int getJ() {
return j;
}
public int getK() {
return k;
}
}
}
Output...
1
2
3
Java streams have a powerful method called flatMap(), which lets you map each element in the stream to another stream, and then returns all of the streams joined together. So it does exactly what you're asking for, all in one method. In your particular case, you are using integers, so they even have a specific method for this case called flatMapToInt(), which allows you to use a stream of primitive integer values, rather than their boxed equivalents. Here's a simple one-liner using your given example:
IntStream expandedStream = originalStream.flatMapToInt((t) -> IntStream.of(t.i, t.j, t.k));
This just turns each element (named t here) into an IntStream containing t.i, t.j, and t.k. When the method returns, it returns a stream that is made up of all of those 3 element streams combined.
I have the following incomplete class. It implements a method that takes any Number object as a parameter and constrains it to a limit stored in a long and then returns the original value or the constrained value. However, the returned constrained value must be of the same concrete type as the input parameter.
public class Max implements Constraint {
long max;
public Number constrain(Number n) {
if (n.longValue() <= max) {
return n;
}
// return a number of the type passed in with value max
}
}
There are other questions about creating an object of the same type as another, but the answers assume a no-arg constructor is available and this is not the case for the numeric types.
I have played with:
n.getClass().getConstructor(new Class<?>[] { n.getClass() }).newInstance(max);
but I still have issues about passing in the right parameter even here. I am back to square one. In any case, it isn't very elegant.
I know I can do it with a lot of if statements, but I am looking for something smarter.
Because the constuctor of SubClasses of Number takes primitives as parameter, you cannot look for the constructore that has the Wrapper Class as parameter
The constructor that they all have, is the String one
long max;
public Number constrain(Number n) {
if (n.longValue() <= max)
try{
return n.getClass()
.getConstructor(String.class)
.newInstance(String.valueOf(max));
}catch(Exception ex){ex.printStackTrace();}
return n;
}
public static void main(String[]args){
Max m = new Max();
m.max = 10;
System.out.println(m.constrain(new Double(25)).getClass()); // class java.lang.Double
System.out.println(m.constrain((int) 18).getClass()); // class java.lang.Integer
}
Working DEMO
with Java 5 or hogher you can use a generic in your methods like this
package test;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Assert;
public class Max {
Number max;
public <T extends Number> T constrain(T n) {
if (n.floatValue() <= max.floatValue()) {
return n;
} else {
return castTo(max, n.getClass());
}
}
#SuppressWarnings("unchecked")
private <T extends Number> T castTo(Number max2, Class<? extends Number> class1) {
if (class1.equals(AtomicInteger.class)) {
return (T) new AtomicInteger(max2.intValue());
} else if (class1.equals(AtomicLong.class)) {
return (T) new AtomicLong(max2.longValue());
// these case are dangerous to handle
} else if (class1.equals(BigDecimal.class)) {
return (T) BigDecimal.valueOf(max2.doubleValue());
} else if (class1.equals(BigInteger.class)) {
return (T) BigInteger.valueOf(max2.longValue());
// Std Case
} else if (class1.equals(Byte.class)) {
return (T) (Byte) max2.byteValue();
} else if (class1.equals(Double.class)) {
return (T) (Double) max2.doubleValue();
} else if (class1.equals(Float.class)) {
return (T) (Float) max2.floatValue();
} else if (class1.equals(Integer.class)) {
return (T) (Integer) max2.intValue();
} else if (class1.equals(Long.class)) {
return (T) (Long) max2.longValue();
} else if (class1.equals(Short.class)) {
return (T) (Short) max2.shortValue();
} else {
throw new IllegalArgumentException("Can't handle this kind of Number : " + class1.getName());
}
}
public static void main(String[] args) {
Max max = new Max();
max.max = 32;
Integer constrain = max.constrain(33);
Assert.assertEquals(Integer.class, constrain.getClass());
Assert.assertEquals(max.max, constrain);
Double constrain2 = max.constrain(33d);
Assert.assertEquals(Double.class, constrain2.getClass());
Assert.assertEquals(max.max.doubleValue(), constrain2, 0);
Float constrain3 = max.constrain(33f);
Assert.assertEquals(Float.class, constrain3.getClass());
Assert.assertEquals(max.max.floatValue(), constrain3, 0);
Short constrain4 = max.constrain((short) 33);
Assert.assertEquals(Short.class, constrain4.getClass());
Assert.assertEquals(max.max.shortValue(), constrain4, 0);
Byte constrain5 = max.constrain((byte) 33);
Assert.assertEquals(Byte.class, constrain5.getClass());
Assert.assertEquals(max.max.byteValue(), constrain5, 0);
Long constrain6 = max.constrain(33l);
Assert.assertEquals(Long.class, constrain6.getClass());
Assert.assertEquals(max.max.longValue(), constrain6, 0);
BigDecimal constrain7 = max.constrain(BigDecimal.valueOf(33));
Assert.assertEquals(BigDecimal.class, constrain7.getClass());
BigInteger constrain8 = max.constrain(BigInteger.valueOf(33));
Assert.assertEquals(BigInteger.class, constrain8.getClass());
AtomicInteger constrain9 = max.constrain(new AtomicInteger(33));
Assert.assertEquals(AtomicInteger.class, constrain9.getClass());
AtomicLong constrain10 = max.constrain(new AtomicLong(33));
Assert.assertEquals(AtomicLong.class, constrain10.getClass());
}
}
but inside your code to construct all child of number there no common constructor the safest way is to reduce the case you want handle here i didn't handle all Striped64 children
I discovered:
import org.apache.commons.beanutils.ConvertUtils;
...
return (Number)ConvertUtils.convert(max, n.getClass());
I haven't looked at the source, but I doubt it is very clever inside. I believe it just hosts a collection of type converters.
So this is an alternative - not better than the other answers, but at least it is concise.
Edit - v3 - without String.
If you only talk about members of Numbers that allows primitive type as the input of constructor like Float/Double/Integer/Long/..., the following could work:
//Number n is valid someInput;
//Note this only works for Classes that take a single numeric value as input
Class type = (Class) n.getClass().getDeclaredField("TYPE").get(n);
return n.getClass().getConstructor(type).newInstance(max)
Things like BigInteger will not work with this one.
Edit - v2
It seems like, for primitive types n, if the "Number n" is replaced by different signatures and by using Integer.TYPE (or Float.TYPE and etc.) you might pass in the 'int' as parameters of getConstructor. You may use n.TYPE here (but as a reminder TYPE is the class member, and it may pop some warning).
n.getClass().getConstructor(n.TYPE).newInstance(max);
Still, as #azro pointed out: if you insist not using string and want it smart, you still need branches and it could be nastier: you need to consider all subclasses of Number, including BigInteger.
True, casting it to string is nasty, but otherwise, you may need to wrap each subclass of Number with an extra class that allows the non-primitive type as args of the constructor. I barely think if-statements is nastier.
Original Answer
I am not very familiar with Reflection.
But a major problem here is the constructor of Numbers are either String or primitive types like 'int', and you cannot really utilize 'int' as the input of getConstructor.
at least, the following may work.
//assume n is some Number object.
n.getClass().getConstructor(String.class).newInstance(max.toString());
This works as classes like Float/Integer/BigInt.../ have constructors that take String as the input.
private List getEnumFromType(List vars, List enums) {
List enumList = new ArrayList<>();
for (Bean.Var var : vars) {
String typeWithoutTypeIdentifierPrefix = var.getType().substring(1,var.getType().length());
for (Enum enumVal : enums) {
if (typeWithoutTypeIdentifierPrefix.equals(enumVal.getName())) {
if (!enumList.contains(enumVal)) {
enumList.add(enumVal);
}
}
}
}
return enumList;
}
You have chained two terminal stream operators.
.forEach() returns void, hence the second .forEach() complains that it can't find a stream to work with.
You may want to read some of the Java 8 Stream documentation before continuing.
Don't do this.
Don't get the idea that the Java 8 Stream API should be used every time you are looping through a collection. It's not a wildcard that you can use to replace all enhanced for loops, especially nested ones.
Your error occurs because you are trying to call forEach on the return value of forEach. Since your for loops are nested, the calls to forEach should also be nested in the stream version. The second for loop should be put in a place like this:
.forEach(countries -> countries.getFromZone().getCountries().stream().filter(country ->country.getCode().equals(selectedCountry).forEach(...))
But seriously, Don't do this.
Your code is very messy in the stream version. It is far less readable than the for loops, mainly because you have a nested for loop. Instead of trying to rewrite your code using streams, you should try to abstract out the logic of your current code. Extract some methods for example:
for (Rate rate : product.getrates()) {
if (rateMatches(value)) { // I tried to guess what you are trying to do here. If you have better names please use yours
for (Countrys countrys : rate.getFromCountry().getCountries()) {
if (countrys.getCode().equals(selectedCountry)) {
updateDisplay(value);
break;
}
}
}
}
This way it's much more clearer.
Don't complicate too much, think of it on simple terms. Keep in mind streams are also about making easier to follow code:
find all Rate/Countrys pairs that match your criteria
For each of them, update value accordingly.
Java streams approach (there are more alternatives):
public void yourMethod() {
X product = ...;
Y value = ...;
Z selectedCountry = ...;
if (product.getRates() == null || product.getRates().isEmpty()) {
return;
}
product.getRates().stream()
.filter(r -> matchesValueRate(r, value))
.flatMap(this::rateCountrysPairStream)
.filter(p -> matchesSelectedCountry(p, selectedCountry))
.forEach(p -> updateValue(p, v));
}
public boolean matchesValueRate(Rate candidate, Y value) {
return value.getAtrribute().getRateType().getCode().equalsIgnoreCase(candidate.getRateType().getCode()) && ...; // add your tzone filter also
}
public Stream<Pair<Rate, Countrys>> rateCountrysPairStream(Rate rate) {
return rate.getFromCountry().getCountries().stream().map(c -> Pair.of(rate, c));
}
public boolean matchesSelectedCountry(Pair<Rate, Countrys> candidate, Z selectedCountry) {
return selectedCountry.equals(candidate.second().getCode());
}
public void updateValue(Pair<Rate, Countrys> rateCountry, Y value) {
Rate rate = rateCountry.first();
Countrys country = rateCountry.second();
// do your display stuff here
}
public static class Pair<K, V> {
private final K first;
private final V second;
private Pair(K first, V second) {
this.first = first;
this.second = second;
}
public static <K, V> Pair<K, V> of(K first, V second) {
return new Pair<>(first, second);
}
public K first() {
return first;
}
public V second() {
return second;
}
}
How do I stop the compiler from complaining at map.get()?
"Type mismatch: cannot convert from ClassInfo<capture#1-of ?> to ClassInfo<T>"
class Context
{
final private Map<Class<?>,ClassInfo<?>> map = new HashMap<>();
<T> ClassInfo<T> getClassInfo(Class<T> c)
{
ClassInfo<T> ci = map.get(c);
if (ci == null) {
ci = new ClassInfo<T>(c);
map.put(c, ci);
}
return(ci);
}
}
Some more information:
ClassInfo contains data about Class, gathered via reflection.
The compiler error does NOT occur with the JDK javac, only when using the Eclipse compiler.
I fixed the problem adding a ()cast to the code:
import java.util.HashMap;
import java.util.Map;
class Context
{
private final Map<Class<?>,ClassInfo<?>> map = new HashMap<Class<?>,ClassInfo<?>>();
<T> ClassInfo<T> getClassInfo(Class<T> c)
{
#SuppressWarnings("unchecked")
ClassInfo<T> ci = (ClassInfo<T>) map.get(c);
if (ci == null) {
ci = new ClassInfo<T>(c);
map.put(c, ci);
}
return(ci);
}
}
Be aware though, casts are usually dangerous, and you should only use them if you are really sure that object is in fact what you are expecting.
The downside of this solution is that it will create a warning, which I had to suppress. Hope it helps!
Just cast it and use :
#SuppressWarnings("unchecked")
ClassInfo<T> ci = (ClassInfo<T>) map.get(c);
Make sure that you are putting Type T into the hash map other wise casting exception can happen.
That is if T represents String, then map.get(c) should always return either null or ClassInfo
I'm not sure why this doesn't work in Java:
import java.util.Map;
public class FreqCounter<T,R> {
private Map<T, Integer> hist;
private R item;
public FreqCounter (final R item_) {
item = item_;
}
public T getMostFrequentElement() {
T most_frequent_element = T();
Integer highestcount = 0;
for(T t : item) {
Integer count = hist.get(t);
if(count == null) {
hist.put(t, 1);
}
else {
hist.put(t, count + 1);
}
if(count + 1 > highestcount) {
most_frequent_element = t;
highestcount = count + 1;
}
}
return most_frequent_element;
}
}
class HelloWorld {
public static void main(String[] args) {
String s = "aaabbcccc";
FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s);
}
}
Problem lines:
1. T most_frequent_element = T();
2. for(T t : item)
3. FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s);
Cannot find symbol: method T()
required: array or java.lang.Iterable, found: R
Required java.lang.Integer
Found: java.lang.String
reason: actual argument java.lang.String cannot be converted to java.lang.Integer by method invocation conversion
What I was trying to do was make a class that could count how many times an element in an iterable container shows up. Originally I just wanted to make it to count characters in a string but I thought I could make it more general. I think some of this would work in C++?
Also, does FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s); need to be "newed" as opposed to declared on the stack?
T is a Generic type, not a real one, and one of the limitations of generics is that you cannot instantiate a new one (which is what I think you were trying to do here).
What you can do though is assign, call methods in, keep references too, duplicate references too, etc.
What you probably actually wanted to do was pull the set of Ts out of the keySet of the Map.
T t = null;
int count = 0;
for (Entry<T, Integer> e: hist.entrySet()) {
if (e.getValue() > count) {
count = e.getValue();
t = e.getKey();
}
}
return t;
Java Generics provide a lot of the same functionality that C++ templates do, but they work in quite a different way. Quite apart from anything else you only have one ArrayList class no matter how many different ways you instantiate one. The generics are used for compiler time type checking and then erased and are not present at all during run time.