Organize similar functions in a class - java

I have a method that gets a matrix of 11xm values (m is variable), analyzes the data and returns an array of features based on that matrix.
I've already written a long function to process this data, however, I wanted to convert it to a class since I will need to extend it later.
My issue is related to how I should organize some functions.
I thought about having a "get" function for each feature extracted from the raw data.
the problem is that different functions will need the same exact preliminary calculations.
For example, I have many x&y points, and I will first need to calculate the pairwise distances, then velocities, then accelerations, and angles. Then all this data will be used to calculate some features.
For example, in the following, if I need to call preliminary1 for both feature 1 & 2, that's twice the work, and I might actually need the same preliminary calculations for 4 or 5 subsequent features (functions). I might need some more calculations for feature 3 that would also need preliminary 1.
Any ideas on how to do this?
private double[] preliminary1(double[], double[]) { some calculations}
private double[] preliminary2(double[]) {
value = preliminary1(value1, value2);
// more calcuations }
public double getFeature1() {
value = preliminary1(value1, value2);
// more calcuations }
public double getFeature2() {
value = preliminary1(value1, value2);
// more calcuations }
public double getFeature3() {
value = preliminary2(value1);
// more calcuations }

Related

How to efficiently store a set of tuples/pairs in Java

I need to perform a check if the combination of a long value and an integer value were already seen before in a very performance-critical part of an application. Both values can become quite large, at least the long will use more than MAX_INT values in some cases.
Currently I have a very simple implementation using a Set<Pair<Integer, Long>>, however this will require too many allocations, because even when the object is already in the set, something like seen.add(Pair.of(i, l)) to add/check existence would allocate the Pair for each call.
Is there a better way in Java (without libraries like Guava, Trove or Apache Commons), to do this check with minimal allocations and in good O(?)?
Two ints would be easy because I could combine them into one long in the Set, but the long cannot be avoided here.
Any suggestions?
Here are two possibilities.
One thing in both of the following suggestions is to store a bunch of pairs together as triple ints in an int[]. The first int would be the int and the next two ints would be the upper and lower half of the long.
If you didn't mind a 33% extra space disadvantage in exchange for an addressing speed advantage, you could use a long[] instead and store the int and long in separate indexes.
You'd never call an equals method. You'd just compare the three ints with three other ints, which would be very fast. You'd never call a compareTo method. You'd just do a custom lexicographic comparison of the three ints, which would be very fast.
B* tree
If memory usage is the ultimate concern, you can make a B* tree using an int[][] or an ArrayList<int[]>. B* trees are relatively quick and fairly compact.
There are also other types of B-trees that might be more appropriate to your particular use case.
Custom hash set
You can also implement a custom hash set with a custom, fast-calculated hash function (perhaps XOR the int and the upper and lower halves of the long together, which will be very fast) rather than relying on the hashCode method.
You'd have to figure out how to implement the int[] buckets to best suit the performance of your application. For example, how do you want to convert your custom hash code into a bucket number? Do you want to rebucket everything when the buckets start getting too many elements? And so on.
How about creating a class that holds two primitives instead? You would drop at least 24 bytes just for the headers of Integer and Long in a 64 bit JVM.
Under this conditions you are looking for a Pairing Function, or generate an unique number from 2 numbers. That wikipeia page has a very good example (and simple) of one such possibility.
How about
class Pair {
int v1;
long v2;
#Override
public boolean equals(Object o) {
return v1 == ((Pair) o).v1 && v2 == ((Pair) o).v2;
}
#Override
public int hashCode() {
return 31 * (31 + Integer.hashCode(v1)) + Long.hashCode(v2);
}
}
class Store {
// initial capacity should be tweaked
private static final Set<Pair> store = new HashSet<>(100*1024);
private static final ThreadLocal<Pair> threadPairUsedForContains = new ThreadLocal<>();
void init() { // each thread has to call init() first
threadPairUsedForContains.set(new Pair());
}
boolean contains(int v1, long v2) { // zero allocation contains()
Pair pair = threadPairUsedForContains.get();
pair.v1 = v1;
pair.v2 = v2;
return store.contains(pair);
}
void add(int v1, long v2) {
Pair pair = new Pair();
pair.v1 = v1;
pair.v2 = v2;
store.add(pair);
}
}

int vs Integer vs a user made class to achieve effective pass by reference behavior in Java

Let's say you have a class of object with three
integer fields that you want to possibly change, all in the same way, with one method.
Let's keep it simple and say all that the method does is add 1 to the parameter passed to it.
That is to say, the desired behavior is that by the time the method has completed, the relevant field has increased by 1.
This is impossible to achieve in Java using the primitive type "int" for those fields.
I know about how Java is "always" pass by value, and not pass by reference,
- and - i've heard whisperings on the internet that this is one reason that the Integer class exists, along with other object "wrapper" classes
for ordinarily primitive types such as int and double.
Sending an object as an argument to a method should, in theory, provide a way to [effectively, if not technically] pass by reference, since the value that is passed, is supposedly the value of the reference to the object.
Very tricky. BUT - and this is where my annoyance comes in - I've tried achieving this very simple task by passing an Integer argument instead of an
int, and the desired behavior was still not accomplished. 1 was not added to the relevant field.
And yet, when I made my very own object, which consisted of just one field, an int value, and passed an instance of this object as an argument
to an appropriate method which would simply add 1 to the passed parameter, the desired behavior was in fact accomplished. 1 was added to the relevant field.
So the questions orbiting around this query are - Is it really going to be necessary to craft my own homemade class just to carry a simple integer value
every time I want to achieve this desired behavior? Can the existing tool provided by Java, Integer, really not perform this simple task?
Instead of having one nice, neat method to handle all three of the hypothetical integer fields i mentioned in the beginning, I felt compelled (in a separate, similar project that ultimately provoked this line of thinking) to make a separate method corresponding to each of the three fields, with essentially the same exact code in each one. This seems very inefficient.
It may not seem like a big deal, on the surface, to write three similar methods instead of one, but to clarify why this dismays me - imagine instead of an object with three integer fields as I stated, there are say, i don't know, four thousand. It would be so much better to write just one thing to perform the same kind of behavior, instead of copying and pasting (and changing whatever little bits necessary) four thousand times.
So I suppose the ultimate question is,
Why doesn't Integer function in a reasonable way? What's the point of wrapping a primitive in an Object at all, if it doesn't even help perform something this simple? Am I missing something simple about how to get Integer to function in the desired way? (Hopefully so) The answer seems close yet infuriatingly out of reach since "RInteger" produces the desired behavior, yet "Integer" doesn't.
The entire source code I used while trying to figure out how to construct this painstaking question is below.
package r9mp;
import javax.swing.SwingUtilities;
public class RefTest2 {
//[main m]
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new RefTest2();
}
});
}
//[fields]
int i;
Integer I;
RInteger RI;
//[constr]
public RefTest2(){
intTest();
IntegerTest();
RIntegerTest();
display();
}
//[methods]
private void intTest(){
i = 100;
intMethod(i);
}
private void IntegerTest(){
I = 100; //boxing? auto?
IntegerMethod(I);
I = 100; //just in case.
IntegerMethod2(I);
}
private void RIntegerTest(){
RI = new RInteger(100);
RIntegerMethod(RI);
}
private void intMethod(int ipar){
ipar = ipar + 1;//no change. expected.
}
private void IntegerMethod(Integer IPar){
IPar = IPar + 1;//no change. frustrating.
pln("From inside IntegerMethod: IPar = " + IPar );
pln("From inside IntegerMethod: I = " + I );
}
private void IntegerMethod2(Integer IPar){
IPar = new Integer(IPar+1);//still no change. there are no set methods for Integer, or I'd try them.
}
private void RIntegerMethod(RInteger riPar){
riPar.value = riPar.value + 1;
}
private void display(){
pln(
"Display... \n" +
"i: " + i + "\n" +
"I: " + I + "\n" +
"RI: " + RI + "\n" +
"--------"
);
}
private void pln(){
pln("");
}
private void pln(String s){
System.out.println(s);
}
//[internal class]
private class RInteger{
int value;
public RInteger(int v){
value = v;
}
public String toString(){
return ""+value;
}
}
}
And, here is the output...
How about one method for primitives and their wrappers?
private int incInteger(int value)
{
return value + 1;
}
and call for it:
int intVal = 100;
intVal = incInteger(intVal);
Integer integerVal = 200;
integerVal = incInteger(integerVal);
First of all, you need to read up on immutability to find out why it is a very good thing to have. There even exist entire languages (functional, mostly) that capitalize on it.
Once you have read about that, then read Eric Lippert's series of articles on immutability. Start here: https://blogs.msdn.microsoft.com/ericlippert/2007/11/13/immutability-in-c-part-one-kinds-of-immutability/ Mind = blown.
But to give you a quick hint as to why primitive wrappers like Integer are immutable, let me just say that these classes are often used as keys in Hash Maps, and a key must be immutable, so that its hashCode will never change, otherwise the hash map will fail with very difficult to track down behaviour. Mutable keys in hashmaps are nasty bugs.
You can achieve what you want with a class of your own devise which plays the role of a reference, or by simply passing an array and modifying the element at array[0].
My personal preferences are as follows:
I would try to do as much as possible with return values.
When return values are inapplicable, (as the case is with invokeLater,) then inner/nested/anonymous classes that have access to the fields of the enclosing class are my next preference.
When that's not an option either, then special classes crafted precisely for the application at hand are my next option. (MyMutableNumberWrapper.)
And when I just want something quick and dirty, then general-purpose classes like Ref<T> (or even single-element arrays) would be my final option.

Java - What is this asking me to do?

It's as follows:
I highlighted the part that I don't understand. What exactly does it mean when it's asking me to make those methods accept only two parameters? It seems like you would need 3, which are the test scores for each respective test?
The code I have so far:
public class Student {
private String ID;
private double test1;
private double test2;
private double test3;
private double average;
public Student(String sID, double sTest1, double sTest2, double sTest3, double sAverage)
{
ID = sID;
test1 = sTest1;
test2 = sTest2;
test3 = sTest3;
average = sAverage;
}
public Student(String sID)
{
ID = sID;
}
public void setTestScore(double sTest1, double sTest2, double sTest3)
{
}
public void getTestScore(double sTest1, double sTest2, double sTest3)
{
}
public double calcAverage()
{
average = (test1 + test2 + test3) / 3;
return average;
}
public void displayInfo(String ID, double test1, double test2, double test3, double average)
{
System.out.println("Student ID: " + ID);
System.out.println("Test 1 Score: " + test1);
System.out.println("Test 2 Score: " + test2);
System.out.println("Test 3 Score: " + test3);
System.out.println("Average test score: " + average);
}
}
Any insight as to what it's expecting me to do with the getTestScore and setTestScore methods would be appreciated.
Edit: Looks like the solution is to just use an array to store the values? I thought that would defeat the purpose of structuring it this way but it seems like as a beginner my options are a bit limited.
What exactly does it mean when it's asking me to make those methods accept only two parameters? It seems like you would need 3, which are the test scores for each respective test?
That would be one way to do it, but they want to do it slightly differently.
They want to have a method that sets the score only for a single test.
That is probably better as it
can be adapted easily to a greater number of tests
allows to set the scores one-by-one (as you may not even know the other scores yet).
So the "extra" parameter specifies which test you are talking about here.
To set all three scores, you would call this method three times (with different parameters).
Setter should have 2 parameters: test number and score
public void setTestScore(int testNo, double score) {
//YOUR HOMEWORK
}
Getter should return the score for the test number
public double getTestScore(int testNo) {
return YOUR_HOMEWORK;
}
Your Assignment in this case is to think of a good data structure to hold the results of a number of tests (currently three) and to retrieve them at a later time.
Hint: as others here have already suggested, you might think of a datastructure to map key values (your test number) to values (your score). The most basic of these structures being an array where the index is your key (watch out: zero-based!) and score is the value at that index...
With Arrays
You could still have some way of initialization to specify how many tests there are to be. Lets for a moment think of double[] scores = new double[3]; as a member variable in your class. Setting the 3rd test to score would be as simple as scores[2] = score;. Getting the result of the first test simply is scores[0];
The set method shouldn't accept all 3 scores at once. It should accept a single score parameter and a second parameter (int whose value is between 1 to 3) to indicate which test score should be updated.
Similarly the get method should accept the test number (between 1 and 3) and return the corresponding score.
The first method should add a test and a score to a Collection, let's say a HashMap<Integer, Double>. Like this:
public void addScore(int testId, double score) {
myTestsMap.put(testId, score);
}
The second part should retrieve the score from the map, like this:
public double getScoreForTest(int testId) {
if(myTestsMap.containsKey(testId){
return myTestsMap.get(testId);
} else {
return -1;
}
}
myTestsMap should be a class field so it's state is kept. Create it in the constructor like that:
myTestsMap = new HashMap<Integer, Double>;
As for a theoretical background:
the two methods are so-called getter and setter. It is a good practice to keep your class fields private and only allow access through such methods. It allows you to analyze the in-coming and out-going data, among other things.
Map is a data structure which maps a set of unique keys to non-unique values. HashMap is one of Map's implementations.
Another option not mentioned here is to hold your test scores in an ArrayList:
public class Student {
private String ID;
private ArrayList<Double> testScores = new ArrayList<>();
//CONSTRUCTOR
public void setTestScore(int testNumber, double score) {
//YOUR HOMEWORK
}
public double getTestScore(int testNumber) {
//YOUR HOMEWORK
}
Now you can add your test scores and they can be positional based on the index in the list. Note that ArrayList is also 0-based, so you'll have to correct for that. This approach also gives you the added benefit of being able iterate through test scores and print them out in the correct order.
The student object should have a Map<Integer, Double> field that stores the test number as the key and the score they got on that test as the value. The set method will put(testNumber, score) and the get method will return the test score by get(testNumber);
What seems confusing perhaps is the requirement to provide a constructor that sets all fields? Perhaps you expect the constructor method signature to look just like the setTestScore method?
If you're still in need of help, try to think a second about what the lesson is about. Are you learning about collections?
What exactly does it mean when it's asking me to make those methods accept only two parameters? It seems like you would need 3, which are the test scores for each respective test?
Try thinking about what the method is supposed to do, rather than how you would go about doing it.
The name of the method is a giveaway - setTestScore.
That would indicate to me, that I want to set the score for a single test.
Now, I would ask myself, what information would I need to change the score for a single test?
I would need something that identifies an individual test. E.g the integer 0 for test 1, integer 1 for test 2 etc.
I would also need the actual test score, so that I can store it.
Now I know that I likely need two parameters, one for the test identifier, and one for the test score.
So now, I need a way to store the test score in a specific place using the identifier.
Given that I have an identifier which is an integer, it should hopefully be clear that I would want to use an array.
The reason I would choose an array is because it accepts an integer, and allows me to access the data at that place in the array.
A section of pseudocode to highlight what I have proposed above:
setTestScore ( parameter1 testIdentifier, parameter2 testScore )
ArrayOfTestScores[testIdentifier] = testScore
Note regarding your second question
It seems like you would need 3, which are the test scores for each
respective test?
If someone sent you the following information in an email,
and asked you to store/update the value for a student's test in an excel sheet:
no value
65.7
no value
Sure, you can see right away you need to update the student's second test.
But, is there a better way?
How about the person just sends me the test number and the score?
Test 2: 65.7
Seems to be easier, because I have an actual identifier for the test to be updated.
And I also don't need redundant information in the email.
When starting off with programming it can help to try and turn the problem into a real life example which you can hopefully relate to. It could help you understand what makes sense and what doesn't. Eventually, as problems get trickier, you will likely need to learn some formal approaches to problem solving. But for this example, making a simple real life equivalent of what you're doing can help.
Ideally you would want to have everything object oriented, that would mean that the Test themselves would be their own class.
I think what is expected is that the first value is the number of the test (1 through 3) and the second value is the actual value. So the method signature that you have is wrong. It should just have two paramters. The first being the number and the second being the score.
What happens after the setter is called?
Well... you have to decide on some structure to store that data. It is basically three pairs of data. Like I mentioned before, it would be nice to have a Test class, but a simple data structure should suffice. I will give you a hint about the data structure : it should be key/value based. The key is the id of the Test, and the value is the value of the test. Have a read about java collections to see if there is any kind of data structure that can help you with this.
I think you are supposed to create a Map of some kind, with the test ID as a key, and the score as a value.
Your setter would populate the map with the score for the current test ID.
Your getter would retrieve the score in the map, corresponding to the asked test ID.
What exactly does it mean when it's asking me to make those methods
accept only two parameters? It seems like you would need 3, which are
the test scores for each respective test?
the method should accept test-id and test-score, and set data to proper attribute,
public void setTestScore(int testNumber, double testScore)
{
if(testNumber == 1)
test1=testScore;
else if(testNumber == 2)
test2=testScore;
else if(testNumber == 3)
test3=testScore;
}
and get method should take 1 param (testNumber)
public double getTestScore(int testNumber){
if(testNumber == 1)
return test1;
else if(testNumber == 2)
return test2;
else if(testNumber == 3)
return test3;
}

Return two Strings from method

I'm a beginner in Java programming, and I'm trying to make a voting machine program, where you can vote for Republicans or Democrats. My question is, how can I edit my method so I would be able to return two strings with two distinct values?
For example, look at my code all the way in the bottom. It's wrong, but I wanted the tester to be able to print out Democrats: (some number) and Republicans: (some number) in one method. How can I do that?
import java.lang.String;
public class VotingMachine1 {
private double Democrats;
private double Republicans;
public VotingMachine1() {
Democrats = 0;
Republicans = 0;
}
public void voteRepublican() {
Republicans = Republicans + 1;
}
public void voteDemocrat() {
Democrats = Democrats + 1;
}
public void clearMachineState() {
Republicans = 0;
Democrats = 0;
}
//this is where I'm having difficulties. I know its wrong
public double getTallies() {
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
}
No return is necessary there, since you aren't leaving a function. To do what you seem to want to do, just replace that last method with the following:
public void getTallies()
{
System.out.println("Democrats: " + Double.toString(Democrats));
System.out.println("Republicans: " + Double.toString(Republicans));
}
Also, since your votecounts should only ever be integers, there's no reason to declare them as doubles instead of ints.
What you are looking for here is a format string. A format string is used when you know what your output should look like, and only have a few "holes" where unknown data should be filled in. To output your data using format strings, you would use the System.out.format(String, Object...) method:
System.out.format("Democrats: %f\n", Democrats);
System.out.format("Republicans: %f\n", Republicans);
In this case, the %f indicates that a floating-point number (since your variables are declared as double) will be printed instead of the %f. However, you may wish to consider declaring them as int (or long) instead, in which case you would use %d instead of %f in the format strings.
Finally, you ought to change your getTallies() method to return void instead of double, as you are printing the values, not returning them.
Your code and your description are so contradictory, it is not clear that you even know what you are trying to do. I believe that this is the real root of your problems.
Here goes:
public double getTallies()
{
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
First, your question says that you want to "return two strings with two values" ... but you have declared the method as returning one double.
Next, your code is printing values ... not returning them.
You've also made some major mistakes at the syntactic level, largely (I believe) because you are trying to do contradictory things:
return Republicans is not a valid Java expression, so you can't use it as a argument to the println method.
The println method can't be called with two arguments, as your code is trying to do. There is a zero argument version and a number of one argument overloads ... but no overloads with two or more arguments.
Basically, you need to start by making up your mind about what this method is supposed to do. Is it supposed to:
return the tallies (as two doubles)?
return a string representing the two tallies?
return nothing ... and output the two tallies to standard output?
do something else?
Once you've made up your mind:
code the method to do what you've decided it should do, and
chose a method name that correctly reflects what it is supposed to do. Hint: a method that starts with get is conventionally a "getter" that returns the attribute or attributes themselves ... not a String rendering.
double is a bad choice of type for a vote count too:
You cannot have a fractional vote.
You want to represent vote counts precisely and floating point types (like double) are not precise. (Or at least, not in the sense that you require.)
When you attempt to format or output a double, the resulting character string is likely to include a pesky decimal point ... or worse.
You should use int or long instead of double.
Finally, this is a serious Java style violation, and should get you a significant penalty if your marker is paying attention.
private double Democrats;
private double Republicans;
Variable names in Java should start with a LOWER CASE letter.
A few more random comments:
import java.lang.String; is superfluous as all classes in package java.lang are automatically imported in every Java source file.
Votes can not be fractional. People can't vote 0.75 candidate A, and 0.25 candidate B. If you use integer datatypes (int or long), you will be reflecting this fact better. Also, you will be saving yourself a lot of headache when you start obtaining results like 379857.999999. This is because floating point types have a better range, but worse precision (especially noticeable when working with pure integers).
According to Java usual naming conventions, variable names should start with a lowecase letter.
A better name for function getTallies is printTallies.
For output purposes, it's much better to use string formatting than concatenation. Some advantages are: multiple formats supported, ease of use, and internationalization.
Putting all together:
private int democratVotes;
private int republicanVotes;
public void printTallies() {
System.out.format("Democrats: %,d%n",democratVotes);
System.out.format("Republicans: %,d%n",republicanVotes);
}
In this particular case, votes will be printed with thousand separation (ex: 3,345,623 instead of 3345623). Check Java's Formatting Numeric Print Output tutorial.
Thinking better about it, there are some alternatives where getTallies would effectively be returning some form of value:
1) Make it to return a String with both tallies. It would be hard and inefficient to separate the tallies later, though.
public String getTallies() {
return "Democrats: %,d votes. Republicans: %,d votes.%n".format(democratVotes,republicanVotes);
}
2) Make it to return an array.
public int[] getTallies() {
return new int[2]{ democratVotes, republicanVotes };
}
public int[] getTallies1() { // Same as getTallies, but written step by step.
int[] result= new int[2] ;
result[0]= democratVotes ;
result[1]= republicanVotes ;
return result ;
}
3) Make it to return a class.
public VotingMachineResults getTallies() {
return VotingMachineResults(democratVotes,republicanVotes) ;
}
public static class VotingMachineResults {
private int democratVotes;
private int republicanVotes;
public VotingMachineResults(democratVotes,republicanVotes) {
this.democratVotes= democratVotes ; // `this` required to disambiguate field democratVotes from parameter democratVotes.
this.republicanVotes= republicanVotes ;
}
public int getDemocratVotes() {
return democratVotes ;
}
public int getRepublicanVotes() {
return republicanVotes ;
}
}
As you can see, this class is very similar to VotingMachine1, but it does not accept internal state changes. It is a "value" class.
In Java, you concatenate Strings with the + operator. Proper syntax for what you were trying to do looks like this:
System.out.println("Democrats: " + Democrats);
System.out.println("Republicans: " + Republicans);
A return statement is only used when you want to return some object or value to a method that called your current method. It is not appropriate in this place since you're only passing a value to another method (println()).
ALSO, you need to fix your getTallies() method. Make it return void instead of double since you aren't returning anything.
Here's something completely different: why not override toString()?
Presumably, any instance of VotingMachine1 will apply for all votes that you care about for that instance. That is to say, you don't create a new instance of a VotingMachine1 every time someone casts a vote.
So, what you can do is override the toString() method. We'll also use String.format() to handle the numerical values.
#Override
public String toString() {
// assumes that Democrats and Republicans are declared as int
// since it's pointless to indicate percentages of a vote
return String.format("Democrats: %d\nRepublicans: %d", Democrats, Republicans);
}
Now, whenever you vote, you can use the toString() method to get the information (which is called whenever one does System.out.println(object).
VotingMachine1 voter = new VotingMachine1();
voter.voteDemocrat();
voter.voteRepublican();
System.out.println(voter);
/* This prints:
Democrats: 1
Republicans: 1
*/
A less specific answer to your question would be to return an Object called (say) Votes
public class Vote {
int democratVotes
int republicanVotes
}
and then make your VotingMachine class simply return an instance of this object (suitably changed to make it immutable).
On my project we have created a generic version of this called a Tuple that returns a pair of values in a single object - it has an overloaded toString method for easy printing.
you can return an array with [0] and [1] as key and devide it on the basis of your need..
like
returnArray[0]="first string";
returnArray[1]="second string";
and use it ur way...

Code duplication caused by primitive types: How to avoid insanity?

In one of my Java projects I am plagued by code repetition due to the way Java handles (not) primitives. After having to manually copy the same change to four different locations (int, long, float, double) again, for the third time, again and again I came really close (?) to snapping.
In various forms, this issue has been brought up now and then on StackOverflow:
Managing highly repetitive code and documentation in Java
How to avoid repetition when working with primitive types?
Passing dynamic list of primitives to a Java method
The consensus seemed to converge to two possible alternatives:
Use some sort of code generator.
What can you do? C'est la vie!
Well, the second solution is what I am doing now and it is slowly becoming dangerous for my sanity, much like the well known torture technique.
Two years have passed since these questions were asked and Java 7 came along. I am, therefore, hopeful for an easier and/or more standard solution.
Does Java 7 have any changes that might ease the strain in such cases? I could not find anything in the condensed change summaries, but perhaps there is some obscure new feature somewhere?
While source code generation is an alternative, I'd prefer a solution supported using the standard JDK feature set. Sure, using cpp or another code generator would work, but it adds more dependencies and requires changes to the build system.
The only code generation system of sorts that seems to be supported by the JDK is via the annotations mechanism. I envision a processor that would expand source code like this:
#Primitives({ "int", "long", "float", "double" })
#PrimitiveVariable
int max(#PrimitiveVariable int a, #PrimitiveVariable int b) {
return (a > b)?a:b;
}
The ideal output file would contain the four requested variations of this method, preferrably with associated Javadoc comments e.t.c. Is there somewhere an annotation processor to handle this case? If not, what would it take to build one?
Perhaps some other trick that has popped up recently?
EDIT:
An important note: I would not be using primitive types unless I had a reason. Even now there is a very real performance and memory impact by the use of boxed types in some applications.
EDIT 2:
Using max() as an example allows the use of the compareTo() method that is available in all numeric boxed types. This is a bit trickier:
int sum(int a, int b) {
return a + b;
}
How could one go about supporting this method for all numeric boxed types without actually writing it six or seven times?
I tend to use a "super type" like long or double if I still want a primitive. The performance is usually very close and it avoids creating lots of variations. BTW: registers in a 64-bit JVM will all be 64-bit anyway.
Why are you hung up on primitives? The wrappers are extremely lightweight and auto-boxing and generics does the rest:
public static <T extends Number & Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
This all compiles and runs correctly:
public static void main(String[] args) {
int i = max(1, 3);
long l = max(6,7);
float f = max(5f, 4f);
double d = max(2d, 4d);
byte b = max((byte)1, (byte)2);
short s = max((short)1, (short)2);
}
Edited
OP has asked about a generic, auto-boxed solution for sum(), and will here it is.
public static <T extends Number> T sum(T... numbers) throws Exception {
double total = 0;
for (Number number : numbers) {
total += number.doubleValue();
}
if (numbers[0] instanceof Float || numbers[0] instanceof Double) {
return (T) numbers[0].getClass().getConstructor(String.class).newInstance(total + "");
}
return (T) numbers[0].getClass().getConstructor(String.class).newInstance((total + "").split("\\.")[0]);
}
It's a little lame, but not as lame as doing a large series of instanceof and delegating to a fully typed method. The instanceof is required because while all Numbers have a String constructor, Numbers other than Float and Double can only parse a whole number (no decimal point); although the total will be a whole number, we must remove the decimal point from the Double.toString() before sending it into the constructor for these other types.
Does Java 7 have any changes that might ease the strain in such cases?
No.
Is there somewhere an annotation processor to handle this case?
Not that I am aware of.
If not, what would it take to build one?
Time, or money. :-)
This seems to me like a problem-space where it would be difficult to come up with a general solution that works well ... beyond trivial cases. Conventional source code generation or a (textual) preprocessor seems more promising to me. (I'm not an Annotation processor expert though.)
If the extraordinary verbosity of Java is getting to you, look into some of the new, higher-level languages which run on the JVM and can interoperate with Java, like Clojure, JRuby, Scala, and so on. Your out-of-control primitive repetition will become a non-issue. But the benefits will go much further than that -- there are all kinds of ways which the languages just mentioned allow you to get more done with less detailed, repetitive, error-prone code (as compared to Java).
If performance is a problem, you can drop back into Java for the performance-critical bits (using primitive types). But you might be surprised at how often you can still get a good level of performance in the higher-level language.
I personally use both JRuby and Clojure; if you are coming from a Java/C/C#/C++ background, both have the potential to change the way you think about programming.
Heh. Why not get sneaky? With reflection, you can pull the annotations for a method (annotations similar to the example you've posted). You can then use reflection to get the member names, and put in the appropriate types... In a system.out.println statement.
You would run this once, or each time you modded the class. The output could then be copy-pasted in. This would probably save you significant time, and not be too hard to develop.
Hm ,as for the contents of the methods... I mean, if all your methods are trivial, you could hard code the style (ie if methodName.equals("max") print return a>b:a:b etc. Where methodName is determined via reflection), or you could, ummmmm... Hm. I'm imagining the contents can be easily copy pasted, but that just seems more work.
Oh! Whty not make another annotation called " contents ", give it a string value of the method contents, add that to the member, and now you can print out the contents too.
In the very least, the time spent coding up this helper, even if about as long as doing the tedious work, well, it would be more interesting, riiiight?
Your question is pretty elaborate as you already seem to know all the 'good' answers. Since due to language design we are not allowed to use primitives as generic parameter types, the best practical answer is where #PeterLawrey is heading.
public class PrimitiveGenerics {
public static double genericMax( double a, double b) {
return (a > b) ?a:b;
}
public int max( int a, int b) {
return (int) genericMax(a, b);
}
public long max( long a, long b) {
return (long) genericMax(a, b);
}
public float max( float a, float b) {
return (float) genericMax(a, b);
}
public double max( double a, double b) {
return (double) genericMax(a, b);
}
}
The list of primitive types is small and hopefully constant in future evolution of the language and double type is the widest/most general.
In the worst case, you compute using 64 bit variables where 32 bit would suffice. There is a performance penalty for conversion(tiny) and for pass by value into one more method (small), but no Objects are created as this is the main (and really huge) penalty for using primitive wrappers.
I also used a static method so it is bound early and not in run-time, although it is just one and which is something that JVM optimization usually takes care of but it won't hurt anyway. May depend on real case scenario.
Would be lovely if someone tested it, but I believe this is the best solution.
UPDATE:
Based on #thkala's comment, double may only represent long-s until certain magnitude as it loses precision (becomes imprecise when dealing with long-s) after that:
public class Asdf2 {
public static void main(String[] args) {
System.out.println(Double.MAX_VALUE); //1.7976931348623157E308
System.out.println( Long.MAX_VALUE); //9223372036854775807
System.out.println((double) Long.MAX_VALUE); //9.223372036854776E18
}
}
From the performance point of view (I make a lot of CPU-bound algorithms too), I use my own boxings that are not immutable. This allows using mutable numbers in sets like ArrayList and HashMap to work with high performance.
It takes one long preparation step to make all the primitive containers with their repetitive code, and then you just use them. As I also deal with 2-dimensional, 3-dimensional etc values, I also created those for myself. The choice is yours.
like:
Vector1i - 1 integer, replaces Integer
Vector2i - 2 integer, replaces Point and Dimension
Vector2d - 2 doubles, replaces Point2D.Double
Vector4i - 4 integers, could replace Rectangle
Vector2f - 2-dimensional float vector
Vector3f - 3-dimensional float vector
...etc...
All of them represent a generalized 'vector' in mathematics, hence the name for all these primitives.
One downside is that you cannot do a+b, you have make methods like a.add(b), and for a=a+b I chose to name the methods like a.addSelf(b). If this bothers you, take a look at Ceylon, which I discovered very recently. It's a layer on top of Java (JVM/Eclispe compatbile) created especially to address it's limitations (like operator overloading).
One other thing, watch out when using these classes as a key in a Map, as sorting/hashing/comparing will go haywire when the value changes.
I'd agree with previous answers/comments that say there isn't a way to do exactly what you want "using the standard JDK feature set." Thus, you are going to have to do some code generation, although it won't necessarily require changes to the build system. Since you ask:
... If not, what would it take to build one?
... For a simple case, not too much, I think. Suppose I put my primitive operations in a util class:
public class NumberUtils {
// #PrimitiveMethodsStart
/** Find maximum of int inputs */
public static int max(int a, int b) {
return (a > b) ? a : b;
}
/** Sum the int inputs */
public static int sum(int a, int b) {
return a + b;
}
// #PrimitiveMethodsEnd
// #GeneratedPrimitiveMethodsStart - Do not edit below
// #GeneratedPrimitiveMethodsEnd
}
Then I can write a simple processor in less than 30 lines as follows:
public class PrimitiveMethodProcessor {
private static final String PRIMITIVE_METHODS_START = "#PrimitiveMethodsStart";
private static final String PRIMITIVE_METHODS_END = "#PrimitiveMethodsEnd";
private static final String GENERATED_PRIMITIVE_METHODS_START = "#GeneratedPrimitiveMethodsStart";
private static final String GENERATED_PRIMITIVE_METHODS_END = "#GeneratedPrimitiveMethodsEnd";
public static void main(String[] args) throws Exception {
String fileName = args[0];
BufferedReader inputStream = new BufferedReader(new FileReader(fileName));
PrintWriter outputStream = null;
StringBuilder outputContents = new StringBuilder();
StringBuilder methodsToCopy = new StringBuilder();
boolean inPrimitiveMethodsSection = false;
boolean inGeneratedPrimitiveMethodsSection = false;
try {
for (String line;(line = inputStream.readLine()) != null;) {
if(line.contains(PRIMITIVE_METHODS_END)) inPrimitiveMethodsSection = false;
if(inPrimitiveMethodsSection)methodsToCopy.append(line).append('\n');
if(line.contains(PRIMITIVE_METHODS_START)) inPrimitiveMethodsSection = true;
if(line.contains(GENERATED_PRIMITIVE_METHODS_END)) inGeneratedPrimitiveMethodsSection = false;
if(!inGeneratedPrimitiveMethodsSection)outputContents.append(line).append('\n');
if(line.contains(GENERATED_PRIMITIVE_METHODS_START)) {
inGeneratedPrimitiveMethodsSection = true;
String methods = methodsToCopy.toString();
for (String primative : new String[]{"long", "float", "double"}) {
outputContents.append(methods.replaceAll("int\\s", primative + " ")).append('\n');
}
}
}
outputStream = new PrintWriter(new FileWriter(fileName));
outputStream.print(outputContents.toString());
} finally {
inputStream.close();
if(outputStream!= null) outputStream.close();
}
}
}
This will fill the #GeneratedPrimitiveMethods section with long, float and double versions of the methods in the #PrimitiveMethods section.
// #GeneratedPrimitiveMethodsStart - Do not edit below
/** Find maximum of long inputs */
public static long max(long a, long b) {
return (a > b) ? a : b;
}
...
This is an intentionally a simple example, and I'm sure it doesn't cover all cases, but you get the point and can see how it could be extended e.g. to search multiple files or use normal annotations and detect method ends.
Furthermore, whilst you could set this up as a step in your build system, I set this up to run as a builder before the Java builder in my eclipse project. Now whenever I edit the file and hit save; it's updated automatically, in place, in less than a quarter of a second. Thus, this becomes more of a editing tool, than a step in the build system.
Just a thought...

Categories