G'day comrades. I have a problem.
I have two methods which are completely duplicate apart from that they are accessing a different field. I cannot pass the field value as a parameter because accessing takes place inside a loop (simplified example):
public final class Thing {
ImmutableList<Box> boxes;
public int getNumberOfApples() {
int total = 0;
for (Box box : boxes) {
total += box.getApplesCount();
}
return total;
}
public int getNumberOfPears() {
int total = 0;
for (Box box : boxes) {
total += box.getPearsCount();
}
return total;
}
}
I could put my fruit into a map and passed the field name as a parameter but it looks dirty and I am quite happy with the current class composition. So the question is - how do I refactor my code to have a single method of type:
public int getNumberOfFruit(SomethingMagic) {
moreMagic;
return total;
}
Cheerio.
Well, you could have something like:
public interface Function<In, Out> {
Out apply(In input);
}
Then:
public int getCount(Function<Box, Integer> projection) {
int total = 0;
for (Box box : boxes) {
total += projection(box);
}
return total;
}
For the moment constructing that projection will be ugly, e.g.
int pears = thing.getCount(new Function<Box, Integer>() {
#Override public Integer apply(Box input) {
return box.getPearsCount();
}
});
but in Java 8, it'll be much simpler with lambda expressions:
int pears = thing.getCount(box -> box.getPearsCount());
Note that Raffaele Rossi's answer is slightly more specific than mine by making the interface non-generic. This means it can be more efficient, as there's no need to box the counts - but less reusable, of course. Which approach you decide to use is a judgement call which will largely depend on your actual use case.
I would suggest a functional approach. Define a function to pass into your getNumberOfFruit which will retrieve the number of the correct fruit. Something like:
public interface FruitCounter {
int apply(Box box);
}
public int getNumberOfFruit(FruitCounter counter) {
int total = 0;
for (Box box : boxes) {
total += counter.apply(box);
}
return total;
}
Then pass the proper implementation to count apples or pears:
int numOfApples theThing.getNumberOfFruit(new FruitCounter() {
#Override
public int apply(Box box) {
return box.getApplesCount();
});
int numOfPears theThing.getNumberOfFruit(new FruitCounter() {
#Override
public int apply(Box box) {
return box.getPearsCount();
});
Related
I am trying to pass two variables along to a method and have the method give me back two independent results.
int numX = 5;
int numY = 3;
System.out.println(displayTwiceTheNumber(numX, numY));
}
public static int displayTwiceTheNumber(int numX, int numY) {
int numW, numZ;
numW, numZ = 2 * (numX, numY);
return numW numZ;
}
Java takes it that at numW, numZ = 2 * (numX, numY); that I am trying to redefine numX and numY. How do I phrase the last block to take two variables and give two results?
A single int function can only return 1 int at a time.
If you want to return 2 values, consider calling the function twice or creating a custom object to be used.
You need to change the return type of the function. Currently, the return type is int, so you have to return one integer.
To return two integer, you should consider returning an array or a list or something similar.
public static int[] displayTwiceTheNumber(int numX, int numY){
//your code that do something
int[] ret = {numW, numZ};
return ret;
}
Or knowing that this function would change the value of numW and numZ, you could declare those as global variable. Now, when you call this function, those variable will be changed. Then, you can use numW and numZ subsequently.
public int numW;
public int numZ;
public static void displayTwiceTheNumber(int numX, int numY){
//your code that do something and modifies numW and numZ
}
public static void anotherfunction(){
//after calling displayTwiceTheNumber, numW and numZ would have the appropriate value
//you can now just use numW and numZ directly
}
Overview: Use a tuple. In this example I use an tuple to return more than one result. Tuple means to return more than one result type. In this example I return a tuple of two integer types. My class TupleCustom contains one method function1 which receives two parameters of type integer: x and y. I create a tuple of type integer and return the tuple as a variable. Internally, the precomiler converts the tuple json than back to a tuple with variable Item1, Item2...ItemN in the unit test method.
public class TupleCustom
{
public async Task<Tuple<int, int>> Function1(int x, int y)
{
Tuple<int, int> retTuple = new Tuple<int, int>(x, y);
await Task.Yield();
return retTuple;
}
}
public class TestSuite
{
private readonly ITestOutputHelper output;
public TestSuite(ITestOutputHelper output)
{
this.output = output;
}
[Fact]
public async Task TestTuple()
{
TupleCustom custom = new TupleCustom();
Tuple<int, int> mytuple = await custom.Function1(1,2);
output.WriteLine($" Item1={mytuple.Item1} Item2={mytuple.Item2} ");
}
When I have this problem I create a private utility class for handling the return values. By doing it this way, you can pass various types in the argument list. Aspects of the class can be tailored to your requirements.
public static void main(String [] args) {
int numX = 5;
double numY = 3.0;
Nums n = displayTwiceTheNumber(numX, numY);
System.out.println(n.numX);
System.out.println(n.numY);
}
public static Nums displayTwiceTheNumber(int numX, double numY) {
int numW;
double numZ;
// do something with arguments.
// in this case just double them and return.
return new Nums(2*numX, 2*numY);
}
private static class Nums {
int numX;
double numY;
public Nums(int nx, double ny) {
this.numX = nx;
this.numY = ny;
}
public String toString() {
return "(" + numX + ", " + numY +")";
}
}
Prints
10
6.0
Say we have variables int a = 0; and int c;.
Is it possible to make it so that c is always equal to something like a + 1 without having to redundantly retype c = a + 1 over and over again
Thanks!
No, it is not possible to make one variable track another variable. Usually, this is not desirable either: when a value of one variable is tied to the value of another variable, you should store only one of them, and make the other one a computed property:
int getC() { return a+1; }
A less abstract example is a connected pair of age and date of birth. Rather than storing both of them, one should store date of birth alone, and make a getter method for computing the current age dynamically.
Since you have 2 variables tied in a specific way, consider using custom object to wrap a and c values. Then you can control the object state inside the class logic. You can do something like this:
public class ValuePair {
private final int a;
private final int c;
public ValuePair(int a) {
this.a = a;
this.c = a + 1;
}
public int getA() {
return a;
}
public int getC() {
return c;
}
}
Firstly, The answer is no, you can't do it directly in Java, but you can redesign your int class, There is an example:
public class Test {
public static void main(String[] args) throws IOException {
MyInt myInt1 = new MyInt(1);
KeepIncrementOneInt myInt2 = new KeepIncrementOneInt(myInt1);
System.out.println(myInt2.getI());
myInt1.setI(2);
System.out.println(myInt1.getI());
System.out.println(myInt2.getI());
}
}
class MyInt { //your own int class for keep track of the newest value
private int i = 0;
MyInt(int i) {
this.i = i;
}
public int getI() {
return this.i;
}
public void setI(int i) {
this.i = i;
}
}
class KeepIncrementOneInt { //with MyInt Class to get the newest value
private final MyInt myInt;
KeepIncrementOneInt(MyInt myInt) {
this.myInt = myInt;
}
public int getI() {
return this.myInt.getI() + 1; //get the newest value and increment one.
}
}
Create your own Int class, because we need a reference type to keep track of the newest the value a. like the MutableInt in apache commons.
Create a always increment 1 class with your own Int class as a member.
In getI method, it's always from the reference Int class get the newest value a.
I have read up on Java Interfaces (callbacks) because I was told by a professor I should use callbacks in one of my programs. In my code, there are two Mathematical functions I can 'pick' from. Instead of making a method activate() and changing the code inside (from one function to the other) when I want to change functions, he said I should use callbacks. However, from what I've read about callbacks, I'm not sure how this would be useful.
EDIT: added my code
public interface
//the Interface
Activation {
double activate(Object anObject);
}
//one of the methods
public void sigmoid(double x)
{
1 / (1 + Math.exp(-x));
}
//other method
public void htan(final double[] x, final int start,
final int size) {
for (int i = start; i < start + size; i++) {
x[i] = Math.tanh(x[i]);
}
}
public double derivativeFunction(final double x) {
return (1.0 - x * x);
}
}
If you want to use interfaces something like this would work.
I have a MathFunc interface that has a calc method.
In the program I have a MathFunc for mutliplication and one for addition.
With the method chooseFunc you can choose one of both and with doCalc the current chosen MathFunc will do the calculation.
public interface MathFunc {
int calc(int a, int b);
}
and you can use it like that:
public class Program {
private MathFunc mult = new MathFunc() {
public int calc(int a, int b) {
return a*b;
}
};
private MathFunc add = new MathFunc() {
public int calc(int a, int b) {
return a+b;
}
};
private MathFunc current = null;
// Here you choose the function
// It doesnt matter in which way you choose the function.
public void chooseFunc(String func) {
if ("mult".equals(func))
current = mult;
if ("add".equals(func))
current = add;
}
// here you calculate with the chosen function
public int doCalc(int a, int b) {
if (current != null)
return current.calc(a, b);
return 0;
}
public static void main(String[] args) {
Program program = new Program();
program.chooseFunc("mult");
System.out.println(program.doCalc(3, 3)); // prints 9
program.chooseFunc("add");
System.out.println(program.doCalc(3, 3)); // prints 6
}
}
I have List<Vector3D> , where Vector3D is a coordinate. I want to find sum of all distance between Vector3D elements of list. I want to find it using java 8 streams. I try to use reduce but it cant help me.
UPD:
Class Vector3D has method double distance(Vector3D) witch find distance between two positions. e.g. i have list with (1,0,0) (2,0,0) (3,0,0). As a result i want to find length of this path. It is 3.
If we are using java 7 or lower we have to do:
public static double calcPathLength(List<Vector3D> path){
double length = 0d;
for (int i=0; i< path.size()-1; i++){
length += path.get(i).distance(path.get(i+1));
}
return length;
}
The operation you are performing is called Mutable reduction.
Pshemo’s answer shows how you can implement such operation ad-hoc by providing the three necessary functions. However, when all three functions are implemented by a dedicated class it might be useful to implement these functions inside a class implementing Collector for easier reuse:
public class Distance implements Collector<Vector3D, Distance.Helper, Double> {
public static final Distance COLLECTOR = new Distance();
static final class Helper {
private double sum = 0;
private Vector3D first = null, previous = null;
}
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
public Supplier<Helper> supplier() {
return Helper::new;
}
public BiConsumer<Helper, Vector3D> accumulator() {
return (helper,vector3d)-> {
if (helper.previous != null)
helper.sum += vector3d.distance(helper.previous);
else helper.first = vector3d;
helper.previous = vector3d;
};
}
public BinaryOperator<Helper> combiner() {
return (h1,h2)-> {
h2.sum += h1.sum;
if(h1.previous!=null && h2.first!=null) {
h2.sum += h1.previous.distance(h2.first);
h2.first=h1.first;
}
return h2;
};
}
public Function<Helper, Double> finisher() {
return helper -> helper.sum;
}
}
You will recognize the three function from the ad-hoc version. New is a fourth function, finisher which allows to specify how the final result can be extracted from the mutable container so we don’t need the getSum() call.
The use case simplifies to:
List<Vector3D> list;
//…
double distance=list.stream().collect(Distance.COLLECTOR);
One of the options would be creating some helper class which would remember previously used vector and based on it calculate difference between it and current vector. This class could look like
class DistanceHelper {
private double sum = 0;
private Vector3D first = null;
private Vector3D last = null;
public void add(Vector3D vector3d) {
if (first == null)
first = vector3d;
if (last != null)
sum += vector3d.distance(last);
last = vector3d;
}
public void combine(DistanceHelper otherHelper) {
//add distance of path from current thread with distance of path
//from other thread
sum += otherHelper.sum;
//also add distance between paths handled by separate threads like
// when path of Thread1 is A->B and Thread2 is C->D then we need to
// include path from `B` to `C`
if (this.last!=null && otherHelper.first!=null)
sum += this.last.distance(otherHelper.first);
this.last = otherHelper.last;
}
public double getSum() {
return sum;
}
}
and you can use it for example with combine instead of reduce like
double sum = list
.stream()//or parallelStream()
.collect(DistanceHelper::new, DistanceHelper::add,
DistanceHelper::combine).getSum();
I have two different types of Sets that need to be iterated and one of the values of the objects of the set need to be summed. How can I do this with Generics, i.e without writing two summing methods for each type of Set?
private Double calculateFooScoreSum(final Set<Foo> fooScoreSet)
{
Double sum = 0.0;
for (final Foo score : fooScoreSet)
{
sum += score.getScore();
}
return sum;
}
private Double calculateBarScoreSum(final Set<Bar> barScoreSet)
{
Double sum = 0.0;
for (final Bar score : barScoreSet)
{
sum += score.getScore();
}
return sum;
}
How can I write the above two methods using Generics as a single method. Something Like:
private static Double calculateScoreSum(Set<?> scoreSet)
{
Double sum = 0.0;
for(Object scoreObj : scoreSet){
//Some casting magic
sum+=score.getScore();
}
return sum;
}
If it helps, getScore() method exists in both classes Foo and Bar.
Any ideas and suggestions are much appreciated.
Thanx
Define a common interface, say Scorable:
public interface Scorable {
int getScore();
}
And implement it with Foo and Bar:
public class Foo implements Scorable {
public int getScore () { return 1; }
}
public class Bar implements Scorable {
public int getScore () { return 2; }
}
And then, define a method that can accept any kind of Scorable, using wildcards:
private static Double calculateScoreSum(Set<? extends Scorable> scoreSet) {
Double sum = 0.0;
for (Scorable score : scoreSet){
sum += score.getScore();
}
return sum;
}
Which can receive either Set<Foo> or Set<Bar> since they both implement Scorable.