I'm using the Java 8 Stream API like this:
private Function<Long, Float> process; // Intermediate step (& types)
private long getWeekFrequency(final ScheduleWeek week) {
return week.doStreamStuff().count(); // Stream<>.count() returns long
}
#Override
public float analyse(final Schedule sample) {
return (float) sample // cast back to float
.getWeeks()
.stream()
.mapToLong(this::getWeekFrequency) // object to long
.mapToDouble(process::apply) // widen float to double
.sum();
}
#Override
public String explain(final Schedule sample) {
return sample
.getWeeks()
.stream()
.map(this::getWeekFrequency) // change stream type?
.map(String::valueOf)
.collect(Collectors.joining(", "));
}
Questions
I assume there is overhead when changing between object/primitive Stream types... How does this compare to the boxing overhead if I stick to Stream<>?
What about if I later change back?
Concretely:
In analyst, should I use .map(...).mapToDouble(...)?
In explain, should I use .mapToLong(...).mapToObj(...)?
So let's break this down:
.mapToLong(this::getWeekFrequency)
gives you a primitive long.
.mapToDouble(process::apply)
This primitive long is boxed to a Long because the process function requires it. process returns a Float which is mapped to a primitive double (via Float.doubleValue()).
These are summed and the sum is cast to a primitive float (narrowing, but you say safe) which is then returned.
So how can we get rid of some of the autoboxing? We want a FunctionalInterface which exactly matches our process function, without using any box classes. There isn't one we can use off-the-shelf, but we can easily define it like so:
#FunctionalInterface
public interface LongToFloatFunction
{
float apply(long l);
}
Then we change our declaration to:
private LongToFloatFunction process;
and keep everything else the same which will prevent any auto-boxing. The primitive float returned by the function will be automatically widened to a primitive double.
Well it seems from your definition that process looks sort of like this:
double process (long value) {
// do something
}
As such if you do : map(...).mapToDouble you would be creating an Object of type Long every time, only to unbox it immediately after to be used in process. I would leave the code as it is to use the primitive implementation that would avoid this.
The second one uses String#valueOf. In case of long, String.valueOf(l) will be called, which works on the primitive: Long.toString(l).
In case of Object the same method will be called, but with the caveat that first boxing happens. So, I would change it to mapToLong
Related
This is my code:
public class Test
{
public static void main(String arg[]) {
new Test().method1(5);
}
public void method1(int b) { // integer method
System.out.println("integer ");
}
public void method1(short a) { // short method
System.out.println("short");
}
}
I am running this class, and it gives me result of integer. Why it is not giving short?
Because the literal 5 is by default understood as an int. If you want to call the method1(short a) method, you need to explicitly do a cast:
new Test().method1((short) 5);
The literal 5 has type int, that's why the method that expects an int is called.
new Test().method1((short)5) would call the method that expects a short.
Default type of Java integer literals is int thats why integer method is getting invoked.
you have to apply type conversion because you are willing to call a function which receives short.
try calling with:(short)5
It's because, as noted in the other answers, a 5 on its own denotes an int. You can denote a long by appending an L, so 5L would be treated as a long. If you want a byte or a short then you have to cast explicitly.
It may be that you have a good reason for wanting a method that takes a short, but please bear in mind that this is quite rare. Certainly you would not want to be doing this for performance reasons. Java uses a 32-bit int by default because pretty much every processor out there can work natively with 32-bit integers. You will probably find that a short will operate more slowly than an int.
(Of course, if you're doing specifically 16-bit arithmetic, then you might still need to use a short.)
I had been thinking of using a generic factory pattern for this, however I just want to make sure that I am using it correctly.
First of all, this has to be Java-based, due to client needs.
My application can instantiate several objects, and each of those objects should be able to change type at run time. For instance, a variable can start out as a float, be converted to an int, then to a char, then back to a float. That would be a basic example, however custom data types can be added in for extra fun.
Is a generic factory pattern the correct one to use in this case? Or, is there something better? To me, the factory pattern seems to be better at instantiating and not updating (unless if I essentially destroyed and re-instantiated the variable).
More detail:
This is an evolutionary algorithm where I don't necessarily know the types when the program starts. It may find that an int is more desirable than a float, based on how evolution goes.
For instance, if I start with a floating point value of 4.34:
// start of program
object var = 4.34;
// evolution running......
...
// evolution determines that var would be better as a float
var.convertToInt();
// var is now an int with a value of 4
My initial thought had been to have a generic factory type object where I keep track of the current 'type' of the object and return the appropriate value. So in the beginning it would return a float, and after the conversion would return the int-converted value (mapped to an internal int).
Edit 2: Code clarification.
I guess my point is just not coming through. Here is an example of what I would expect to see, code-wise.
object var = new object(int, 4); // create int variable with value of 4
// where object is whatever base design pattern i am using here
...
var.toFloat(); // convert var to float, value is now 4.0
System.out.println(var.getValue()); // prints 4.0
...
var.toCustomClass(); // var is now a custom datatype
System.out.println(var.getValue()); // calls the print method of the class
I should also mention that the instance of var needs to persist throughout execution, as it is an object within my evolutionary algorithm and can't be destroyed and re-instantiated as something else.
If you explain why you want to do this it might help. Your best bet based on what you have said so far will be just to always use the type as Number and then store whatever version you need. For example number.toInt, number.toDouble etc.
For more complex types define a common interface that they all implement and store them using that interface, then write appropriate mapping methods or use a library such as Dozer to do the mapping for you.
You are going to need to create your own class to handle this. For example:
public class Value {
Object value;
Object getValue();
void toInteger() {
if (value instanceof Number) {
value = Integer.valueOf(((Number)value).intValue());
} else {
// Handle the conversion however you handle it
}
}
}
Maybe this can help.
By providing a generic method, the return type is casted to the type of the variable to hold the result. A ClassCastException will be launched if the types are not compatible
public class Wrapper {
private Object src;
public Wrapper(Object o) {
src = o;
}
public String getType(){
return src.getClass().getName();
}
public <E> E getValue() {
return (E)src;
}
public void toInteger(){
//dummy implementation
if(src instanceof Double){
src=new Integer(String.valueOf((int)Math.floor((Double)src)));
}
}
public static void main(String args[]){
Wrapper wrapper=new Wrapper(new Double(4.8));
System.out.println(wrapper.getType());
Double myDouble=wrapper.getValue();
System.out.println(myDouble);
wrapper.toInteger();
System.out.println(wrapper.getType());
Integer myInteger=wrapper.getValue();
// Double exceptionInProgress = wrapper.getValue();
System.out.println(myInteger);
}
}
For later reference:
Operations o = new Operations(); //class containing the operation methods
HashMap<String, Method> ops = new HashMap<String, Method>();
I'm working on a program that will parse a mathematical expression input via console or eventually maybe a GUI.
Currently, I have a class called "Operations" which has various basic math functions (more will be added later, just testing right now). In another class, I have a method which calculates the result by taking an operand, the successive operator, and another operand, and invoking a method to evaluate the expression. It stores the info necessary to the calculation in:
double numOne = //...
char operator = //...
double numTwo = //...
double result = //...
Now I don't want to have a long switch/case statement or if statement saying:
if (operator.equals("+")) //I know .equals() doesn't use chars; it's an example
o.add(numOne, numTwo);
else if (operator.equals("-"))
o.subtract(numOne, numTwo);
on and on for every operation. That's why I tried creating a HashMap<String, Method> to store the operator (String) and the method which should be called. Basically, in the current class' constructor, I put:
ops.put("+", o.getClass().getMethod("add", double.class, double.class));
ops.put("-", o.getClass().getMethod("subtract", double.class, double.class));
//etc. Which in and of itself is also pretty lengthy
Now to once the method is identified via operator, I need another method to return a Method to call.
private Method getMethodFromKey(HashMap<String, Method> map, char op) {
Method method = null;
for (Map.Entry<String, Method> e: map.entrySet()) {
if (e.getKey().equals(op))
method = e.getValue();
}
return method;
}
Finally, once I have the correct method, I can call it with:
getMethodFromKey(ops, operator).invoke(o, numOne, numTwo);
That all works great. My problem is, the method(s) I am/will be invoking are getter methods; they return a double. Example:
public double add(double one, double two) {
double answer = 0;
answer = one + two;
return answer;
}
I guess this is all just a long-winded way of asking is there a way to assign the returned value of an innvoked method? Something like:
result = getMethodFromKey(ops, operator).invoke(o, numOne, numTwo); //This doesn't work :(
Any help is appreciated. Additionally, if my aproach is completely wrong, I would appreciate a bump in the right direction.
DISCLAIMER: I'm relatively inexperienced at Java and known for overcomplicating things, so please point out any grievous flaws in my design. :)
invoke() returns Object and since Java does not know how to assign an Object to a double this won't compile. invoke starts by boxing the double from the method into a Double. You have to cast it now from Object to Double (and could then call .doubleValue() but that's done automatically) for that to work.
I'm [...] known for overcomplicating things, so please point out any grievous flaws in my design. :)
Using reflection instead of an interface. A Method is a function object. But it's not type-safe to use. An interface can do the same without those problems.
interface Operation {
double evaluate(double a, double b);
}
Then put objects that implement the interface in your map:
ops.put("+", new Operation() {
public double evaluate(double a, double b) {
return a+b;
});
and you can do
double result = getMethodFromKey(ops, operator).evaluate(numOne, numTwo);
The need to cast is gone.
If you're sure that all of your operations are going to be on a single class (no extensibility), then you should consider using an enum instead. You can add an instance field to the enum to represent the character command corresponding to the operation and then have an abstract evaluate method that's implemented by each enum value.
If invoke() is returning an Object that you know is a double, you can cast it like so:
result = (Double) getMethodFromKey(ops, operator).invoke(o, numOne, numTwo);
Since double is a primitive, which is not of type Object, you need to cast it to a Double, and through unboxing, we get a double.
With autounboxing, this statement will automatically work:
int myPrimitive = (Integer) doIt();
But if I want to explicitly convert from an Integer to an int here in a single line, where do I have to put the parentheses?
You could do this :
int myPrimitive = (int) (Integer) doIt();
But as you said, auto-unboxing will get that for you.
A bad example to show that chain casts work (don't ever use this code) :
Map notReallyAMap = (Map) (Object) new String();
The thing with chain casts, is that wherever you use it, either the cast is legit, and you can remove intermediaries; or the cast will simply cause a ClassCastException. So you should never use it.
Either the compiler unboxes the Integer for you, or you do it yourself - this cannot be avoided.
So you need to either do
int myPrimitive = ((Integer) doIt()).intValue();
or more simply, change doIt() to return an int since you seem to want to deal with ints rather than (null-able) Integers.
Running this code:
public class SomeSet {
public static void main(String[] args) {
Set<Short> s = new HashSet<Short>();
for (short i = 0; i < 100; i++) {
s.add(i);
s.remove(i - 1);
}
System.out.println(s.size());
}
}
Will print the value 100.
Why does it print this value?
s.remove(i - 1);
The line above will attempt to remove Integer objects from the set, because all integer calculations in Java have int (or long) results. Since the set contains Short objects, the remove() method will not have any effect.
This (and similar problems) is the main reason why you should almost never use short (and, more so, Short). Using a Set implementation to contain autoboxed numbers incurs a massive (easily 1000%) overhead, so it's rather pointless to try and save space by using Short rather than Integer.
The problem is that remove(i-1) calls the remove method with an Integer object, since i-1 is of type int (which gets auto-boxed into an Integer).
To make sure that you call remove with a Short object use this:
s.remove((short) (i - 1));
The type of i - 1 is int, so it gets autoboxed to an Integer.
Normally you'd expect a generic collection to prevent you performing operations which have arguments of the wrong type, but the interface to Set<E> is a bit loose.
Because the remove method of Set<E> takes an Object rather than an E, the compiler doesn't warn you that you're removing a different type to what the set contains.
To force it to be a Short, cast the numeric value to (short). (casting to (Short) isn't allowed, and you'd have to cast the numeric value to use Short.valueOf)
Note that the add method is generically typed boolean add(E o) so in your case of Set the add method will take a short, whereas the remove method is not generically typed boolean remove(Object o) so i - 1 autoboxes to a Integer. For any value of i new Short(i).equals(new Integer(i)) will always be false.
Note that if you try s.add(i - 1); you will get a compiler error because i - 1 becomes an instance of Integer and the types Integer and Short do not match.