I hope you can help me as I am new to Java-8
public class main {
public static void main(String[] args){
ArrayList<Double> coll1 = new ArrayList<>();
coll1.add(2.5);
coll1.add(3.5);
printColl(multi(coll1));
}
public static ArrayList<Double> multi(ArrayList<Double> coll1) {
return coll1.replaceAll(aDouble -> aDouble*2.0);
}
public static void printColl(ArrayList<?> coll) {
coll.stream().forEach(System.out::println);
}
}
I have the following problem: I have an ArrayList with 2 Doubles, which I am trying to modify with the method "multi". I use the method "replaceAll" to change the single values with the lambda-expression but I get an error.
The error is "incompatible types. Required: java.util.List Found: void"
I hope you can help me as I really dont know why I am getting this error.
Let's have a look at the replaceAll method signature:
public void replaceAll(UnaryOperator<E> operator)
as you can see it does not return anything, that means it modifies the existing ArrayList.
so in your case, you would need to do something like:
public static ArrayList<Double> multi(ArrayList<Double> coll1) {
coll1.replaceAll(aDouble -> aDouble*2.0);
return coll1;
}
Related
I am wondering if ya'll can help me get a better grip on generics.
I have simplified this question as much as possible.
I am trying to save the element stored in a linked list in a variable called saveIt. I know LinkedList itself uses generics, so I want my variable to take up whatever data type is in the list. I believe LinkedList itself designates that type as E, but when I try to declare a variable as 'E saveIt' I get "cannot resolve symbol E."
public class Main {
public static void main(String[] args) {
// whatever goes here ...
}
void saveElement(LinkedList input) {
E saveIt = input.getFirst();
}
}
If I make the LinkedList then I can declare a variable as 'Integer saveIt' but that isn't what I want to do.
public class Main {
public static void main(String[] args) {
// whatever goes here ...
}
void saveElement(LinkedList<Integer> input) {
Integer saveIt = input.getFirst();
}
}
I considered declaring 'Object saveIt' but I'm not sure whether that is the right approach. The concept of datatype E obviously exists in Java, and isn't quite the same as Object (or is it?), so why can't I access it (or how can I access it)?
public class Main {
public static void main(String[] args) {
// whatever goes here ...
}
void saveElement(LinkedList input) {
Object saveIt = input.getFirst();
}
}
So, basic question is if I want to have my method address whatever datatype is in the list, how do I do that?
<E> void saveElement(LinkedList<E> input) {
E saveIt = input.getFirst();
}
You need to tell Java that E is a type parameter of your method -- it's like another thing that's being passed in! -- and that the LinkedList contains elements of type E.
I would like to create a class that store a list of methods references and then executes all of them using Java 8 Lambda but I have some problem.
This is the class
public class MethodExecutor {
//Here I want to store the method references
List<Function> listOfMethodsToExecute = new LinkedList<>();
//Add a new function to the list
public void addFunction(Function f){
if(f!=null){
listOfMethodsToExecute.add(f);
}
}
//Executes all the methods previously stored on the list
public void executeAll(){
listOfMethodsToExecute.stream().forEach((Function function) -> {
function.apply(null);
}
}
}
This is the class that I created for test
public class Test{
public static void main(String[] args){
MethodExecutor me = new MethodExecutor();
me.addFunction(this::aMethod);
me.executeAll();
}
public void aMethod(){
System.out.println("Method executed!");
}
}
But there is something wrong when I pass this::aMethod using me.addFunction.
What is wrong?
You should provide a suitable functional interface which abstract method signature is compatible with your method reference signature. In your case it seems that Runnable instead of Function should be used:
public class MethodExecutor {
List<Runnable> listOfMethodsToExecute = new ArrayList<>();
//Add a new function to the list
public void addFunction(Runnable f){
if(f!=null){
listOfMethodsToExecute.add(f);
}
}
//Executes all the methods previously stored on the list
public void executeAll(){
listOfMethodsToExecute.forEach(Runnable::run);
}
}
Also note that in static main method this is not defined. Probably you wanted something like this:
me.addFunction(new Test()::aMethod);
You can't refer to this in a static context as there is no this
me.addFunction(this::aMethod);
You need to refer to an instance or define your Function to take a Test object.
public void addFunction(Function<Test, String> f){
if(f!=null){
listOfMethodsToExecute.add(f);
}
}
and
me.addFunction(Test::aMethod);
This question already has answers here:
Is there a way to compare lambdas?
(3 answers)
Closed 7 years ago.
I am not sure how I can be sure about equality/immutability of functional interface.
I guess there might be no way to assure equality when I use this syntactic sugar in java 8, please let me know any hint if you have any.
I made a short code snippet for my question.
public interface Element {
void doSomething(int a);
}
and I've tried to add instance of this interface in functional way
public class FunctionSet {
public void doubleUp(int a) {
System.out.println(a*2);
}
public void square(int a) {
System.out.println(a*a);
}
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
FunctionSet functionSet = new FunctionSet();
set.add(functionSet::doubleUp);
set.add(functionSet::square);
System.out.println(set.add(functionSet::doubleUp));
}
}
it prints true which means there were not any equality check and also I can't remove any instance from Set once I add it.
in case I use functional interface as an argument, Is there any way that I can compare those instance somehow?
will appreciate any help, thanks in advance!
You can store your method reference into a variable:
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
FunctionSet functionSet = new FunctionSet();
Element fn = functionSet::doubleUp;
set.add(fn);
set.add(functionSet::square);
System.out.println(set.add(fn));
}
This way it returns false.
When you create the same labmda or method reference in different code locations, it's roughly the same as you would create a new anonymous class in both positions:
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
FunctionSet functionSet = new FunctionSet();
set.add(new Element() {
#Override
public void doSomething(int a) {
functionSet.doubleUp(a);
}
});
set.add(new Element() {
#Override
public void doSomething(int a) {
functionSet.square(a);
}
});
System.out.println(set.add(new Element() {
#Override
public void doSomething(int a) {
functionSet.doubleUp(a);
}
}));
}
So every time it's a different object, though it may look the same. For every encountered method reference separate anonymous class is created at the runtime:
Element e1 = functionSet::doubleUp;
Element e2 = functionSet::doubleUp;
System.out.println(e1.getClass());
System.out.println(e2.getClass());
The output will be like this:
class FunctionSet$$Lambda$1/918221580
class FunctionSet$$Lambda$2/1554547125
So practically it's two distinct objects of two distinct classes. It would be quite difficult to conclude that they do the same thing without comparing their bytecode. Also note that they both capture the functionSet variable, so it should also be ensured that it wasn't changed between two method references.
The only workaround I can think up is to declare all the method references as constants in your code and later reference them instead of using method references directly:
public static final Element FN_DOUBLE_UP = new FunctionSet()::doubleUp;
public static final Element FN_SQUARE = new FunctionSet()::square;
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
set.add(FN_DOUBLE_UP);
set.add(FN_SQUARE);
System.out.println(set.add(FN_DOUBLE_UP));
}
Can someone please tell me what am i not seeing.
Exercise from a book.
Create a class called SortingTest. In it, create a method that accepts an array of int values as a parameter and prints out to the terminal the elements sorted.(smallest elements first)
When trying to compile, I'm getting an error:incompatible types.
AbcArray cannot be converted to int[]
From my understanding,I'm passing an int[] value to a method that expects an int[] value. (I apologize if my error is so obvious, i'm still learning)
public class AbcArray {
private int[] myArray;
public AbcArray(){
myArray = new int[]{55,58,57,54,56};
}
public int[] theValues(){
return myArray;
}
}
import java.util.Arrays;
public class SortingTest{
public SortingTest() {}
public void sortArray(int[] outsideArray){
Arrays.sort(outsideArray);
System.out.println(outsideArray);
}
}
First issue with your code is wrong constructor in AbcArray code. You need to replace
public ArraysData(){
myArray = new int[]{55,58,57,54,56};
}
with
public AbcArray(){
myArray = new int[]{55,58,57,54,56};
}
Next step is missing code you didn't post. Let's assume it looks as follows:
public class Main{
public static void main(String[] args){
AbcArray a = new AbcArray();
SortingTest st = new SortingTest();
st.sortArray(a);
}
}
Attempt to build this code results in actual argument AbcArray cannot be converted to int[] by method invocation conversion. This happens because you are passing the whole class AbcArray to method sortArray to fix that you need to pass values from AbcArray which are available by using method theValues(). So your code will looks like this:
public class Main{
public static void main(String[] args){
AbcArray a = new AbcArray();
SortingTest st = new SortingTest();
st.sortArray(a.theValues());
}
}
Also you can't print array into standard output. Take a look at Arrays.toString() method before printing anything.
I have a function e.g.
helloworld(list<object> names)
I have the following code :
List<CustomClass> newMe = new ArrayList<CustomClass>();
Now, if i want to pass newMe into helloworld(newMe);. This is not possible because im down casting. How can i overcome this issue? Do i downcast my list to (Object) and then try to upcast it? is there another way? would appreciate an example.
thanks
Change the definition of helloworld to
public void helloworld(List<?> names) {
//method implementation...
}
Take into account that your method won't be able to add or remove elements from the list parameter.
Just use a ? as generic type in your parameter list. Example:
public class Foobar {
public static void helloworld(List<?> names) {
}
public static void main(String[] args) {
List<CustomClass> newMe = new ArrayList<>();
helloworld(newMe);
}
}