Problem Description:
I want to be able to use an ArrayList of Functions passed in from another class (where the Functions have been defined in that other class). If the list of Functions, which may have different input and return types, are defined in one class, I want to be able to pass an ArrayList of some of them, with possible duplicates, as a parameter to some other class's constructor or method and perform operations using them.
Code Description:
The code below is a greatly simplified example which is not intended to make much sense from a design perspective. The focus of the problem is the method getResult() within SomeClass and generally how to use an ArrayList of Functions once you have them.
Attempt to solve the problem:
The getResult() method implementation is an example of one of many attempts to use the Function list. Again, please don't mind the design of the code. It was just done that way to try to make the problem example as short as possible.
Simple tester class
package com.Testing;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
public class Tester {
public static void main(String[] args)
{
// Some functions
Function<Integer, Integer> increment = (Integer input) -> {
return input + 1;
};
Function<Integer, Integer> decrement = (Integer input) -> {
return input - 1;
};
Function<Double, Double> timesPi = (Double input) -> {
return input * 3.14;
};
// list of Functions
List<Function> availableMathOperations = new ArrayList<>();
List<Function> selectedMathOperations = new ArrayList<>();
// populate master list
availableMathOperations.add(increment);
availableMathOperations.add(decrement);
availableMathOperations.add(timesPi);
// Populate random selection list //
// generate random binary number
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(availableMathOperations.size() * 2);
boolean[] bits = new boolean[availableMathOperations.size()];
for (int j = 0; j < availableMathOperations.size(); j++) {
bits[availableMathOperations.size() - 1 - j] = (1 << j & randomNumber) != 0;
}
// add math operations to selectedMathOperations based on binary number
for (int j = 0; j < bits.length; j++) {
if (bits[j]){
selectedMathOperations.add(availableMathOperations.get(j));
}
}
SomeClass someClass = new SomeClass(selectedMathOperations, 1.23);
}
}
Other class
package com.Testing;
import java.util.List;
import java.util.function.Function;
public class SomeClass {
List<Function> operations;
double initialValue;
public SomeClass(List<Function> newOperations, double newInitialValue){
operations = newOperations;
initialValue = newInitialValue;
}
public double getResult(){
double result = 0.0;
// problem method
// perform the random list of operations using the initial value initially
for(int i = 0; i < operations.size(); i++){
if(i == 0)
result = operations.get(i)(initialValue);
else
result += operations.get(i)(result);
}
return result;
}
}
The method of a java.util.function.Function object is apply. You need to call it like this:
operations.get(i).apply(initialValue)
However you use raw Function and therefore the result could be Object and you'd need to convert it to the appropriate type. Also you can't use the + (or the +=) operator with it. I'd suggest restricting the parameter types with Number:
List<Function<Number, ? extends Number>> operations = Arrays.asList(
num -> num.intValue() + 1,
num -> num.intValue() - 1,
num -> num.doubleValue() * 3.14
); // just an example list here
public double getResult() {
double result = 0.0;
for (int i = 0; i < operations.size(); i++) {
if (i == 0) {
result = operations.get(i).apply(initialValue).doubleValue();
} else {
result += operations.get(i).apply(result).doubleValue();
}
}
return result;
}
I'm not convinced I understand correctly, but I think the problem you're facing is how to call the functions in your List? The JavaDoc for the Function interface states that it has a single non-abstract method, apply() that you call to use the Function, as follows:
public double getResult(){
double result = 0.0;
for(int i = 0; i < operations.size(); i++){
if(i == 0)
result = operations.get(i).apply(initialValue);
else
result += operations.get(i).apply(result);
}
return result;
}
As an aside, that method could be tidied up a bit to make it simpler:
public double getResult() {
double result = initialValue;
//Not sure if this if-statement is a requirement, but it is to replicate
//the functionality in the question
if (operations.isEmpty()) {
return 0.0;
}
for (Operation operation : operations) {
result = operation.apply(result);
}
return result;
}
And as others have said in the comments, you should use generics when passing around your List objects (I guess you'll have to use something like List<Function<? extends Number, ? extends Number>)
Related
This question is kind of long... so bear with me please.
I have to convert a SelectionSort method that was covered in my book that was built to sort arrays, and make it generic so that I can enter either doubles or ints into it and have it work.
It doesn't seem to allow generic arrays, so I'm attempting to use an ArrayList. The problem here is since the int and doubles are now in Integer and Double wrappers, it breaks the SelectionSort method.
I've attempted to fix it, but I'm having no luck. I'll post the original SelectionSort method below, and then the class and driver that I'm creating.
Original SelectionSort:
public class SelectionSort {
private int[] data;
private static final Random generator = new Random();
public SelectionSort(int size) {
data = new int[size];
for(int i = 0; i < size; i++) {
data[i] = 10 + generator.nextInt(90);
}
}
public void sort() {
int smallest;
for(int i = 0; i < data.length - 1; i++) {
smallest = i;
for(int index = i + 1; index < data.length; index++) {
if(data[index] < data[smallest]) {
smallest = index;
}
}
swap(i, smallest);
}
}
public void swap(int first, int second) {
int temporary = data[first];
data[first] = data[second];
data[second] = temporary;
}
}
My simple driver program:
public class GenericsDriver {
public static void main(String[] args) {
SelectionSort<Integer> intSort = new SelectionSort<Integer>();
intSort.AddGrade(100);
intSort.AddGrade(90);
intSort.AddGrade(50);
intSort.AddGrade(80);
intSort.AddGrade(95);
intSort.PrintNumbers();
//sort here
intSort.PrintNumbers();
SelectionSort<Double> doubleSort = new SelectionSort<Double>();
doubleSort.AddGrade(100.1);
doubleSort.AddGrade(90.4);
doubleSort.AddGrade(50.7);
doubleSort.AddGrade(100.2);
doubleSort.AddGrade(100.5);
doubleSort.PrintNumbers();
//sort here
doubleSort.PrintNumbers();
}
}
The new class and my attempt to repurpose the SelectionSort method:
import java.util.*;
public class SelectionSort <T> {
private Array<T> numbers;
public SelectionSort() {
numbers = new ArrayList<T>();
}
public void AddGrade(T number) {
numbers.add(number);
}
public void PrintNumbers() {
System.out.println(numbers.toString());
}
public <T extends Comparable<T>> selectionSort() {
int smallest;
for(int i = 0; i < numbers.size(); i++) {
smallest = i;
for(int index = i + 1; index < numbers.size(); index++) {
if(numbers.) {
//I've tried everything here...
//from using number.get(index), and everything else
//I could think of
}
}
}
}
public void swap(int first, int second) {
}
}
As you can see... I haven't had any luck with sort or swap within my new class. I can't get it to work. My instructions have a hint that I should use > in my sort method...but nothing is giving me the ability to use a .compareTo() method.
This is the actual directive from my book:
Write a generic method selectionSort based on the sort program of Fig 19.6 and 19.7 (That's the code I gave above). Write a test program that inputs, sorts and outputs an Integer array and a Float array. Hint: Use > in the type-parameter section for method selectionSort, so that you can use method compareTo() to compare the objects of the type that T represents.
Could someone please give me some guidance here? Thanks.
It seems that you are new to generics. If you want the program to be the way you wrote it, I can point out few mistakes, which you can improve and then try running your program.
In the third code listing where you defined the class as
SelectionSort <T>
The declaration
private Array<T> numbers;
is incorrect because you do not want this Array class, you can instead use the following:
private List<T> numbers;
Also, there is no point declaring the new selectionSort() generic method as
public <T extends Comparable<T>> selectionSort() {
Do you seriously want a Comparable or its sub class to be the return type?
No, you want a List of T to be returned as an output of the selection Sort process.
Please get back if you still have any doubts.
Happy to Help
Dharam
A quick peek at the javadocs (http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html ) shows that Double implements the Comparable interface, which means that it will have a compareTo() method.
The point that your book is trying to force you to get your head around is the concept that you can have multiple types (Integer, Double) that implement the same interface (Comparable), and that you can take advantage of that in your code.
So:
Double firstDouble = Double.valueof(42.0);
Double secondDouble = Double.valueof(43.0);
Integer firstInteger = Integer.valueof(42);
Integer secondInteger = Integer.valueof(43);
so you could write: firstDouble.compareTo(secondDouble) and firstInteger.compareTo(secondInteger) - but by implementing your sort on Comparable (instead of Integer, Double, etc...), you can just use:
numbers.get(i).compareTo(numbers.get(i+1));
hth
Use a comparator. This SO answer has some details. You can use the same concept to define your own comparators. That way your sorting algorithm is truly generic and can handle any data type (complex numbers for example)
I am new to Java, I want to store an array of pair of doubles. My code looks like this:
import java.util.ArrayList;
import java.util.Map.Entry;
List<Entry<Double, Double>> values = new ArrayList<>();
Entry<Double, Double> pair;
// set pair values:
// pair.setKey(0.5); // this method does not exists
// pair.setValue(3.6);
values.add(pair);
How can I initialize the pair variable?
Is there a better structure to store my array of pair of doubles?
Create your own class to represent a pair and add a constructor that takes two arguments:
public class MyPair
{
private final Double key;
private final Double value;
public MyPair(Double aKey, Double aValue)
{
key = aKey;
value = aValue;
}
public Double key() { return key; }
public Double value() { return value; }
}
See this answer for reasons why a Pair does not exist in Java: What is the equivalent of the C++ Pair<L,R> in Java?
You don't want to use Entry it's an INTERFACE, not a CLASS. That interface is used by an implementations of Set when you call entrySet() on a class that implements Map. It basically lets you manipulate the implemented Map as though it were a Set.
What you would do (but can't) is this. If you try to do this you'll see a compiler error along the lines of "Cannot instantiate the type Map.Entry". That's because Map.Entry is an interface, not a class. An interface doesn't contain any real code, so there's no real constructor to run here.
Entry<Double, Double> pair = new Entry<Double, Double>();
If you look at the below docs you can clearly see at the top that it's a "Interface Map.Entry" which means it's an interface.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Map.Entry.html
What you should do instead of trying to instantiate an interface, which is impossible, is create your own class called Pair. Something like this. Remember to change the package if you use the below code.
package org.mike.test;
public class Pair {
private double x = 0.0;
private double y = 0.0;
public Pair(double x, double y)
{
this.x = x;
this.y = y;
}
public Pair()
{
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
After writing your Pair class your code will now look like this.
package org.mike.test;
import java.util.ArrayList;
import org.mike.test.Pair; //You don't need this if the Pair class is in the same package as the class using it
public class tester {
/**
* #param args
*/
public static void main(String[] args) {
ArrayList<Pair> values = new ArrayList<Pair>();
Pair pair = new Pair();
// set pair values:
pair.setY(3.6);
pair.setX(3.6);
values.add(pair);
}
}
Couldn't you just use
public class MyClass<A,B> extends ArrayList{
private A first;
private B second;
public MyClass(A first, B second){
super();
this.first = first;
this.second = second;}
}
and then add some form of add method, along with a first and second accessor & mutator method? I'm sort of new to programming, but this way would seem like it might work, and be accessible to things other than just the DOUBLE, (in case down the road you want to use other types, like Integer, or even String).
You could use a map to solve this.
Is Entry a class you defined? You instantiate it with new.
Entry<Double, Double> pair = new Entry<Double, Double>(d1, d2);
Note I am assuming you defined a constructor that takes 2 doubles, and you have references for d1 and d2.
I suggest you NOT use the Map.Entry class. The semantics for that class are such that the values are a key and a value, fitting with the way Maps work.
The Map.Entry type that you are trying to use is just an interface, and can therefore not be instantiated. If you wanted to (mis)use internal types of Map, then the concrete Map.Entry implementation HashEntry would be an option.
It is however a much better idea to implement you own Pair type. Or to use a Map instead of an array if that suits you needs.
Another approach, and probably the most efficient way to store and array of double pairs is to use a single array of doubles, and use (2*i) and (2*i + 1) as your indexing scheme. Additionally you gain the advantage that the array will be initialized to all 0s when you create it, no additional steps required. Unfortunately there is a little extra coding overhead to implement add() and remove(), but surprisingly, it's probably less than creating your own container class for the pair.
class MyClass {
double[] values;
int count;
MyClass(int initialCapacity) {
values = new double[initialCapacity*2];
}
// adding a pair
void addPair(double x, double y) {
if (count*2 >= values.length) {
values = Arrays.copyOf(values, values.length*2);
}
values[count*2] = x;
values[count*2 + 1] = y;
count++;
}
void remove(int index) {
if (index >= count) throw new IndexOutOfBoundsException();
if (index < --count) {
System.arraycopy(values, (index+1)*2, values, index*2, (count - index) * 2);
}
}
int size() { return count; }
// both these should check that index < count.
double getX(int index) { return values[index*2]; }
double getY(int index) { return values[index*2 + 1]; }
void exampleIteration() {
// getX/Y accessors are examples of how to get
// the values, but it will be more efficient
// in most cases to just access the array
// array directly as so...
for (int i=0 ; i<count ; ++i) {
System.out.printf("%d: (%f,%f)%n", i, values[i*2], values[i*2+1]);
}
}
}
For someone into competitive programming or coding interview questions you may have a requirement to write all the code in a single file/editor window
in that case, you may use inner classes to conveniently make a pair
and then use an object of that class as a pair
if you want to create a stack of Pairs you can create a Pair object and put it in the stack
import java.util.*;
public class PairArray
{
static class Pair{
int a,b;
Pair(int a,int b){
this.a=a;
this.b=b;
}
}
static void main()
{
int a,b,l=10;
Scanner sc = new Scanner(System.in);
Pair array[]= new Pair[l];
for(int i=0;i<l;i++){
a=sc.nextInt();
b=sc.nextInt();
array[i]=new Pair(a,b);
}
for(int i=0;i<l;i++){
System.out.println(array[i].a+" "+array[i].b);
}
}
}
Please find below program which gives count of pairs available in array.
int getPairsCount(int n, int[] arr) {
HashMap<Integer, Integer> hm = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (hm.containsKey(arr[i])) {
hm.replace(arr[i], hm.get(arr[i]) + 1);
} else {
hm.put(arr[i], 1);
}
}
int sum = 0;
for (Map.Entry<Integer, Integer> hmm : hm.entrySet()) {
if (hmm.getValue() / 2 > 0) {
sum += (hmm.getValue() / 2);
}
}
return sum;
}
If you have access to Entry class, you could create a constructor that takes key and value as parameters.
Entry<Double, Double> pair = new Entry<Double, Double>(0.5, 3.6);
values.add(pair);
public <X> X createData(int n)
{
int[] values = new int[n];
Random rand = new Random();
for(int i = 0; i < n; i++)
{
values[i] = rand.nextInt(100);
}
JOptionPane.showMessageDialog(null, values.length);
return (X )values;
}
Hi there, I have cobbled together a small method to return an int array as a generic type (i think?)
The point of this is, I am to call a users method who is going to generate me some data, at which point I then take that data and invoke a method of their selection.
The issue is, when i call this method how can I convert the generic type to its "proper" type so as it invoke the method with this data.
Typically my process will be
1) invoke the user method to get their data(reflection)
2) use this data to invoke their other method(reflection)
Is what I am doing/trying here possible or in the process of making it a generic return type am i ruining everything?
Thanks
If you wan't to return a list then I would do it by defining a Supplier interface,
public interface Supplier<T> extends Serializable {
public T get();
}
Which can be defined as,
public <X> List<X> createData(Supplier<X> datum, Integer length){
List<X> values = new ArrayList<X>();
for(int i = 0; i < length; i++)
{
values.add(datum.get());
}
JOptionPane.showMessageDialog(null, values.size());
return values;
}
and can be used as,
List<Integer> ints = createData(new Supplier<Integer>() {
Random rand = new Random();
#Override
public Integer get() {
return rand.nextInt(100);
}
}, 10);
I have a filter class wherein the user must declare the type (e.g. Filter<Double>, Filter<Float> etc). The class then implements a moving average filter so objects within the class must be added. My question is how to do this? I'm sorry if the answer is simple but I've muddled myself up by thinking about it too much I think :p.
public abstract class FilterData<T>
{
private final List<T> mFilter;
private T mFilteredValue; // current filtered value
protected Integer mSize = 10;
private T mUnfilteredValue; // current unfiltered value
public FilterData()
{
mFilter = new ArrayList<T>();
}
public FilterData(int size)
{
mSize = size;
mFilter = new ArrayList<T>(mSize);
}
public abstract T add(final T pFirstValue, final T pSecondValue);
#SuppressWarnings("unchecked")
public T filter(T currentVal)
{
T filteredVal;
mUnfilteredValue = currentVal;
push(currentVal);
T totalVal = (T) (new Integer(0));
int numNonZeros = 1;
for (int i = 0; i < mFilter.size(); ++i)
{
if (mFilter.get(i) != (T) (new Integer(0)))
{
++numNonZeros;
T totalValDouble = add(mFilter.get(i), totalVal);
totalVal = totalValDouble;
}
}
Double filteredValDouble = (Double) totalVal / new Double(numNonZeros);
filteredVal = (T) filteredValDouble;
mFilteredValue = filteredVal;
return filteredVal;
}
public T getFilteredValue()
{
return mFilteredValue;
}
public List<T> getFilterStream()
{
return mFilter;
}
public T getUnfilteredValue()
{
return mUnfilteredValue;
}
public void push(T currentVal)
{
mFilter.add(0, currentVal);
if (mFilter.size() > mSize)
mFilter.remove(mFilter.size() - 1);
}
public void resizeFilter(int newSize)
{
if (mSize > newSize)
{
int numItemsToRemove = mSize - newSize;
for (int i = 0; i < numItemsToRemove; ++i)
{
mFilter.remove(mFilter.size() - 1);
}
}
}
}
Am I right to include the abstract Add method and if so, how should I extend the class correctly to cover primitive types (e.g. Float, Double, Integer etc.)
Thanks
Chris
EDIT:
Apologies for being unclear. This is not homework I'm afraid, those days are long behind me. I'm quite new to Java having come from a C++ background (hence the expectation of easy operator overloading). As for the "push" method. I apologise for the add method in there, that is simply add a value to a list, not the variable addition I was referring to (made a note to change the name of my method then!). The class is used to provide an interface to construct a List of a specified length, populate it with variables and obtain an average over the last 'x' frames to iron out any spikes in the data. When a new item is added to the FilterData object, it is added to the beginning of the List and the last object is removed (provided the List has reached the maximum allowed size). So, to provide a continual moving average, I must summate and divide the values in the List.
However, to perform this addition, I will have to find a way to add the objects together. (It is merely a helper class so I want to make it as generic as possible). Does that make it any clearer? (I'm aware the code is very Mickey Mouse but I wanted to make it as clear and simple as possible).
What you're trying to do is create a Queue of Number objects with a fixed size, over which you want to calculate an average. With the trivial situation that you have size = 2 and store two integers 1 & 2 you have an average of 1.5 so its reasonable to set the return type of your filter method to double.
You can then write this code similar to this
public abstract class FilterData<T extends Number> {
private final Queue<T> mFilter = new LinkedList<T>();
protected Integer mSize;
public FilterData() {
this(10);
}
public FilterData(int size) {
mSize = size;
}
public double filter(T currentVal) {
push(currentVal);
double totalVal = 0d;
int numNonZeros = 0;
for (T value : mFilter) {
if (value.doubleValue() != 0) {
++numNonZeros;
totalVal += value.doubleValue();
}
}
return totalVal / numNonZeros;
}
public void push(T currentVal) {
mFilter.add(currentVal);
if (mFilter.size() > mSize)
mFilter.remove();
}
public void resizeFilter(int newSize) {
if (mSize > newSize) {
int numItemsToRemove = mSize - newSize;
for (int i = 0; i < numItemsToRemove; ++i) {
mFilter.remove();
}
}
mSize = newSize;
}
}
You should note that this isn't thread safe.
I'm having problems trying to pass an Integer object from a driver class as an argument for function of a SortedArray Generic class I created. From my driver class, I convert the user's int input into an Integer object to be cast onto Comparable of my SortedArray class.
I continue to receive the error: "Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to Comparable". I took a look at some of my classmates' source codes only to find little difference in setting the arguments/parameters yet they have their code working just fine. I've been looking for hours trying to find what error I've made and I still can't find why my Integer object can't be cast to Comparable.
Here's a bit from my SortedArray Class
public class SortedArray implements Comparable{
public int size;
public int increment;
public int top;
Comparable[] a = new Comparable [size];
public SortedArray(int initialSize, int incrementAmount)
{
top = -1;
size = initialSize;
increment = incrementAmount;
}
public int appropriatePosition(Comparable value)
{
int hold = 0;
if(top == -1)
{
return 0;
}
else
{
for(int i = 0; i <= top; i++)
{
if(a[i].compareTo(value) > 0)
{
hold = i;
break;
}
}
}
return hold;
}
public void insert(Comparable value) //The function that my driver class needs to access
{
//Shifting numbers to the top
if(full() == true)
{
Comparable[] tempArray = new Comparable[top + increment];
for(int i= 0; i< size; i++)
{
tempArray[i]= a[i];
a = tempArray;
}
size = top + increment;
}
if(a[appropriatePosition(value) + 1] != null)
{
for(int i = top; i < appropriatePosition(value); i--)
{
a[i + 1] = a[i];
}
}
a[appropriatePosition(value) + 1]= value;
}
Here's the code for my driver class that passes Integer Object insertObj as an argument for SortedArray's insert function.
public class IntDriver {
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
//Creating variables
int data;
boolean check = false;
int choice;
int size = 5;
int increment = 3;
SortedArray b = new SortedArray(size, increment);
//Creating Menu
while(check == false)
{
System.out.println("Please choose through options 1-6.");
System.out.println("1. Insert\n2. Delete\n3. Clear\n4. Smallest\n5. Largest\n6. Exit");
choice = keyboard.nextInt();
switch(choice)
{
case 1:
System.out.println("Type the int data to store in array location.");
data = keyboard.nextInt();
Integer insertObj = new Integer(data);
b.insert(insertObj);// Here's where I lay "insertObj" as an argument for the SortedArray function.
System.out.println("The value " + data + " is inserted");
break;
The problem is that Integer extends java.lang.Comparable, then your Comparable is not a java.lang.Comparable. Look at the error message, your Comparable comes from the default package rather than java.lang:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to Comparable
That is, you can't cast java.lang.Integer to your own class
As mentioned by axtavt, the problem is that you have your own class Comparable. More specifically, what that means is that:
Integer.valueOf(1) instanceof java.util.Comparable == true
Integer.valueOf(1) instanceof Comparable == false
This means that somewhere in your code you have something like:
Object[] a = new Object[] {Integer.valueOf(1);};
Comparable x = (Comparable) a[0];
// or something equivalent, this is likely being passed through layers
// and not being done next to each other like this.
You need to change that to:
Object[] a = new Object[] {Integer.valueOf(1);};
java.util.Comparable x = (java.util.Comparable) a[0];
Even better, you should rename your Comparator class to something that doesn't collide with the standard classes in Java. In general, even though Java has namespacing, you should try to avoid your classes having the same name as the system classes to avoid exactly this kind of confusion.
I haven't put too much effort into this, but wouldn't it just be easier to use a SortedSet implementation (or its child interface NavigableSet) like TreeSet rather than write your own class? That is, unless you wanted duplicate elements...