I would like to create a JSpinner which can take every possible Double value between a specified minimum and a specified maximum.
Also, the JSpinner should be able to display a text instead of a specific value. Let's say our JSpinner can take values from -1 to 10. I would like to display a text, e.g. "Auto", instead of -1 .
How to replace by
Here is the Model I wrote, but it seems not to be enough, because it says in JSpinner there is an error because the text is not a Double.
public class SpinnerSpecialModel
extends AbstractSpinnerModel implements SpinnerMinMaxModel {
public static final double DEFAULT_MINIMUM = 0.0;
public static final double DEFAULT_MAXIMUM = Double.POSITIVE_INFINITY;
public static final double DEFAULT_STEP = 1.0;
public static final double DEFAULT_VALUE = 1.0;
public static final double DEFAULT_SPECIAL_NUMBER = -1.0;
public static final String DEFAULT_SPECIAL_TEXT = "Auto";
private double maximum;
private double minimum;
private double stepSize;
private double currentNumber;
private double specialNumber;
private String specialText;
private Object m_Value;
public SpinnerSpecialModel(double max, double min, double step, double num,
double specialNum, String specialTxt) {
maximum = max;
minimum = min;
stepSize = step;
currentNumber = num;
specialNumber = specialNum;
specialText = specialTxt;
setAccurateValue(num);
}
public SpinnerSpecialModel(double specialNum, String specialTxt) {
this(DEFAULT_MAXIMUM, DEFAULT_MINIMUM,
DEFAULT_STEP, DEFAULT_VALUE, specialNum, specialTxt);
}
public SpinnerSpecialModel() {
this(DEFAULT_SPECIAL_NUMBER, DEFAULT_SPECIAL_TEXT);
}
#Override
public Object getValue() {
if (currentNumber == specialNumber) {
m_Value = specialText;
}
else {
m_Value = currentNumber;
}
return m_Value;
}
#Override
public void setValue(Object value) {
setAccurateValue(value);
}
private void setAccurateValue(Object value) {
if (value instanceof Double) {
double doubleValue = (Double) value;
if (doubleValue != currentNumber) {
if (doubleValue == specialNumber) {
currentNumber = specialNumber;
m_Value = specialText;
}
else if (doubleValue > maximum) {
currentNumber = maximum;
m_Value = maximum;
}
else if (doubleValue < minimum) {
currentNumber = maximum;
m_Value = minimum;
}
else {
currentNumber = doubleValue;
m_Value = doubleValue;
}
fireStateChanged();
}
}
if (value instanceof String) {
String stringValue = (String) value;
if (stringValue.equals(specialText)) {
this.currentNumber = specialNumber;
this.m_Value = specialText;
fireStateChanged();
}
}
}
#Override
public Object getNextValue() {
return getNewValue(+1);
}
#Override
public Object getPreviousValue() {
return getNewValue(-1);
}
/**
*
* #param direction
* #return
*/
private Object getNewValue(int direction) {
double newValue = currentNumber + direction * stepSize;
setAccurateValue(newValue);
return m_Value;
}
#Override
public double getMaximum() {
return maximum;
}
#Override
public double getMinimum() {
return minimum;
}
#Override
public double getStepSize() {
return stepSize;
}
#Override
public void setMaximum(double max) {
maximum = max;
}
#Override
public void setMinimum(double min) {
minimum = min;
}
#Override
public void setStepSize(double step) {
stepSize = step;
}
}
The best and proper way to do this is not as simple as just writing a model, but it is not very complicated. You actually need to write an Editor and a Formatter to have a true MVC spinner:
A class that extends JSpinner : SpecialValuesSpinner.
A class that implements SpinnerModel : SpecialValuesSpinnerModel
A class that extends DefaultEditor and implements DocumentListener : SpecialValuesSpinnerEditor
A class that extends NumberFormatter : SpecialValuesSpinnerFormatter
I am not going to show you the code for all classes, but here is basically what you have to do in each :
SpecialValuesSpinner :
public class SpecialValuesSpinner() extends SpinnerNumberModel {
// in your constructor do this
setModel(new SpecialValuesSpinnerModel(YOUR_SPECIAL_VALUES);
setEditor(new SpecialValuesSpinnerEditor());
}
SpecialValuesSpinnerModel :
public class SpinnerSpecialValuesModel() extends JSpinner {
// in this class you handle the fact that now, you have an
// interval of values and a list of special values that are allowed.
// here is what I did :
#Override
public Object getNextValue() {
return incrValue(+1);
}
#Override
public Object getPreviousValue() {
return incrValue(-1);
}
private Object incrValue(int dir) {
// NB : BigDecimal here because this is what I used,
// but use what you want in your model
BigDecimal result = null;
BigDecimal numberBD = new BigDecimal(getNumber().toString());
BigDecimal stepSizeBD = new BigDecimal(getStepSize().toString());
BigDecimal dirBD = new BigDecimal(dir);
BigDecimal nextValue = numberBD.add(stepSizeBD.multiply(dirBD));
TreeSet<BigDecimal> currentAllowedValues = new TreeSet<BigDecimal>();
currentAllowedValues.addAll(m_SpecialValues);
if (getMaximum() != null) {
currentAllowedValues.add((BigDecimal) getMaximum());
}
if (getMinimum() != null) {
currentAllowedValues.add((BigDecimal) getMinimum());
}
if (isIncludedInBounds(nextValue)) {
currentAllowedValues.add(nextValue);
}
if (dir > 0) {
try {
result = currentAllowedValues.higher(numberBD);
}
catch (NoSuchElementException e) {}
}
else if (dir < 0) {
try {
result = currentAllowedValues.lower(numberBD);
}
catch (NoSuchElementException e) {}
}
return result;
}
}
In SpecialValuesSpinnerEditor, we use Document Listener to have autocompletion (easy to do, just search on SO).
public class SpecialValuesSpinnerEditor extends DefaultEditor implements DocumentListener {
// You have to do in your contructor
SpecialValuesSpinnerFormatter formatter =
new SpecialValuesSpinnerFormatter (spinner.getSpecialValues(), format);
getTextField().setFormatterFactory(new DefaultFormatterFactory(formatter));
}
And now, the most important, the Formatter which does conversion between user input (string) and numbers, and handle the model's display :
public class SpecialValuesSpinnerFormatter extends NumberFormatter {
// Just override the methos StringToValue and ValueToString.
// You can check here if the value is special
// i.e you must display its special text instead. e.g. : "Auto" instead of -1
}
I think you can achieve that by implementing your own SpinnerModel and supplying that as argument to the JSpinner constructor.
Related
public class GPSping {
private double pingLat;
private double pingLon;
private int pingTime;
}
The Trip class
public class Trip {
private ArrayList<GPSping> pingList;
public Trip() {
pingList = new ArrayList<>();
}
public Trip(ArrayList<GPSping> triplist) {
pingList = new ArrayList<>();
}
public ArrayList<GPSping> getPingList() {
return this.pingList;
}
public boolean addPing(GPSping p) {
int length = pingList.size();
int Time = pingList.get(length);
if (p.getTime() > this.pingList[length]) {
pinglist.add(p);
return True;
} else {
return False;
}
}
}
I am trying to add a GPS ping to this trip list but only if the time of p is after the last time in this trip list. I am very new to Java and am struggling with wrapping my head around the syntax some help would be greatly appreciated.
First element in List has index 0, to to get the last one:
int Time = pingList.get(length - 1);
But I think, it's better to store maxPingTime to check it before add new GPSping:
class Trip {
private final List<GPSping> pingList = new ArrayList<>();
private int maxPingTime = Integer.MIN_VALUE;
public List<GPSping> getPingList() {
return pingList.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(pingList);
}
public boolean addPing(GPSping p) {
if (p.getPingTime() <= maxPingTime)
return false;
pingList.add(p);
maxPingTime = p.getPingTime();
return true;
}
}
final class GPSping {
private final double pingLat;
private final double pingLon;
private final int pingTime;
public GPSping(double pingLat, double pingLon, int pingTime) {
this.pingLat = pingLat;
this.pingLon = pingLon;
this.pingTime = pingTime;
}
}
P.S. Pay attention on Encapsulation OOP principle: GPSping should be final and pingList should not be directly retrieved.
I'm learning the concept of neural networks. I decided to try making the neuron class by myself. What is the best way to implement different activation functions in my code? Now it uses only the binary step function.
It's my first try in coding neural networks so if you have any suggestions about my code, or it is completely dumb, please let me know.
Here is my code:
public class Neuron {
// properties
private ArrayList<Neuron> input;
private ArrayList<Float> weight;
private float pot, bias, sense, out;
private boolean checked;
// methods
public float fire(){
pot = 0f;
if (input != null) {
for (Neuron n : input){
if (!n.getChecked()){
pot += n.fire()*weight.get(input.indexOf(n));
} else {
pot += n.getOut()*weight.get(input.indexOf(n));
} // end of condition (checked)
} // end of loop (for input)
} // end of condition (input exists)
checked = true;
pot -= bias;
pot += sense;
out = actFunc(pot);
return out;
} // end of fire()
// getting properties
public float getPot(){return pot;}
public boolean getChecked(){return checked;}
public float getOut(){return out;}
// setting properties
public void stimulate(float f){sense = f;}
public void setBias(float b){bias = b;}
public void setChecked(boolean c){checked = c;}
public void setOut(float o){out = o;}
// connection
public void connect(Neuron n, float w){
input.add(n);
weight.add(w);
}
public void deconnect(Neuron n){
weight.remove(input.indexOf(n));
input.remove(n);
}
// activation function
private float actFunc(float x){
if (x < 0) {
return 0f;
} else {
return 1f;
}
}
// constructor
public Neuron(Neuron[] ns, float[] ws, float b, float o){
if (ns != null){
input = new ArrayList<Neuron>();
weight = new ArrayList<Float>();
for (Neuron n : ns) input.add(n);
for (int i = 0; i < ws.length; i++) weight.add(ws[i]);
} else {
input = null;
weight = null;
}
bias = b;
out = o;
}
public Neuron(Neuron[] ns){
if (ns != null){
input = new ArrayList<Neuron>();
weight = new ArrayList<Float>();
for (Neuron n : ns) input.add(n);
for (int i = 0; i < input.size(); i++) weight.add((float)Math.random()*2f-1f);
} else {
input = null;
weight = null;
}
bias = (float)Math.random();
out = (float)Math.random();
}
}
First, define interface of any activation function:
public interface ActivationFunction {
float get(float f);
}
Then write some implementations:
public class StepFunction implements ActivationFunction {
#Override
public float get() {return (x < 0) ? 0f : 1f;}
}
public class SigmoidFunction implements ActivationFunction {
#Override
public float get() {return StrictMath.tanh(h);}
}
Finally, set some implementation to your Neuron:
public class Neuron {
private final ActivationFunction actFunc;
// other fields...
public Neuron(ActivationFunction actFunc) {
this.actFunc = actFunc;
}
public float fire(){
// ...
out = actFunc.get(pot);
return out;
}
}
as following:
Neuron n = new Neuron(new SigmoidFunction());
Note, neural netoworks are using signal propagation through neurons, where weights are produced. Computing of weight depends also on first derivative of an activation function. Therefore, I would extend ActivationFunction by method, which will return first derivative at specified point x:
public interface ActivationFunction {
float get(float f);
float firstDerivative(float x);
}
So the implemenations will look like:
public class StepFunction implements ActivationFunction {
#Override
public float get(float x) {return (x < 0) ? 0f : 1f;}
#Override
public float firstDerivative(float x) {return 1;}
}
public class SigmoidFunction implements ActivationFunction {
#Override
public float get(float x) {return StrictMath.tanh(x);}
// derivative_of tanh(x) = (4*e^(2x))/(e^(2x) + 1)^2 == 1-tanh(x)^2
#Override
public float firstDerivative(float x) {return 1 - Math.pow(StrictMath.tanh(x), 2);}
}
Then, use actFunction.firstDerivative(x); in fire() method where weight is being computed.
I am currently working on a code that has to find the best solution. First I check whether one of the three is larger than the other two. Hence, there is a maximum that occurs only once. If there are two numbers larger than the third one, but equal to each other, I will have to compare the distance of those two and then the one with the smallest distance is chosen.
The profit functions and distances are calculated outside this method and not that important.
What I have come up with so far is to use a lot of if statements. However, I was wondering whether there would be a more efficient method to do this.
public void bestSolution(List<ROUTE> LS, List<ROUTE> SA, List<ROUTE> RR)
{
int profitLS = profitRoutes(LS);
int profitSA = profitRoutes(SA);
int profitRR = profitRoutes(RR);
int distanceLS = totalDistance(LS);
int distanceSA = totalDistance(SA);
int distanceRR = totalDistance(RR);
if ((profitLS > profitSA) & (profitLS > profitRR))
{
}
}
In case of finding max between three integers -
int mostProfit = Math.max(profitLS, Math.max(profitSA, profitRR));
Considering case - "distance of those two and then the one with the smallest distance is chosen"
class DistanceProfit{
private int profit;
private int distance;
public DistanceProfit(int profit, int distance){
this.profit = profit;
this.distance = distance;
}
}
...
//create DistanceProfit objects add to list
Collections.sort(distenceProfitList, new Comparator<DistenceProfit>{
public int compare(DistenceProfit dp1, DistenceProfit dp2){
if(dp1.getProfit()==dp2.getProfit())
return dp1.getDistance() - dp2..getDistance();
return dp1.getProfit() - dp2.getProfit();
}
});
You could create a TreeSet with the comparison results and select the 'greatest' element.
The comparison result could be something like:
public class ProfitCounter implements Comparable<ProfitCounter>
{
public ProfitCounter(List<ROUTE> route)
{
this.route = route;
profit = profitRoutes(route);
distance = totalDistance(route);
}
#Override
public int compareTo(ProfitCounter other)
{
int result;
result = profit - other.profit;
if (result == 0)
result = other.distance - distance;
return (result);
}
private List<ROUTE> route;
private int profit;
private int distance;
} // class ProfitCounter
Id use something on these lines. Does not limit u to 3 parameters.
public class RouteCalc implements Comparable<RouteCalc> {
private final List routes;
public RouteCalc(List routes) {
this.routes = routes;
}
public static int calcProfit(List routes) {
//use the list to calculate profit
return 0;
}
public static int calcDistance(List routes) {
//use the list to calculate distance
return 0;
}
#Override
public int compareTo(#NonNull RouteCalc another) {
final int profitA = calcProfit(this.routes);
final int profitB = calcProfit(another.routes);
//swap parameters to change from ascending to descending and vice-versa
final int compare = Integer.compare(profitA, profitB);
//if same profit, compare distance
if (compare == 0) {
final int distanceA = calcDistance(this.routes);
final int distanceB = calcDistance(another.routes);
return Integer.compare(distanceA, distanceB);
} else
return compare;
}
//sample usage
public static void main(String args[]) {
final List<RouteCalc> allRoutes = new ArrayList<>();
//add routes
final RouteCalc bestRoute = Collections.max(allRoutes);
}
}
static class CalculatedRoute {
public static CalculatedRoute mostProfitableOf(List<CalculatedRoute> calculatedRoutes) {
return Collections.max(calculatedRoutes, BY_PROFIT_AND_DISTANCE);
}
public static final Comparator<CalculatedRoute> BY_PROFIT_AND_DISTANCE = new Comparator<CalculatedRoute>() {
#Override
public int compare(CalculatedRoute o1, CalculatedRoute o2) {
int cmp = o2.profit - o1.profit;
if (cmp == 0) {
cmp = o1.distance - o2.distance;
}
return cmp;
}
};
private final List<ROUTE> routeList;
private final int profit;
private final int distance;
public CalculatedRoute(List<ROUTE> routeList, int profit, int distance) {
this.profit = profit;
this.distance = distance;
}
public List<ROUTE> getRouteList() {
return routeList;
}
public int getProfit() {
return profit;
}
public int getDistance() {
return distance;
}
}
public List<ROUTE> mostProfitableOf(List<ROUTE> LS, List<ROUTE> SA, List<ROUTE> RR) {
return CalculatedRoute.mostProfitableOf(Arrays.asList(
new CalculatedRoute(LS, profitRoutes(LS), totalDistance(LS)),
new CalculatedRoute(SA, profitRoutes(SA), totalDistance(SA)),
new CalculatedRoute(RR, profitRoutes(RR), totalDistance(RR))
)).getRouteList();
}
I have already made a posting about this program once, but I am once again stuck on a new concept that I am learning (Also as a side note; I am a CS student so please DO NOT simply hand me a solution, for my University has strict code copying rules, thank you.). There are a couple of difficulties I am having with this concept, the main one being that I am having a hard time implementing it to my purposes, despite the textbook examples making perfect sense. So just a quick explanation of what I'm doing:
I have an entity class that takes a Scanner from a driver. My other class then hands off the scanner to a superclass and its two subclasses then inherit that scanner. Each class has different data from the .txt the Scanner read through. Then those three classes send off their data to the entity to do final calculations. And that is where my problem lies, after all the data has been read. I have a method that displays a new output along with a few methods that add data from the super along with its derived classes.EDIT: I simply cannot figure out how to call the instance variable of my subclasses through the super so I can add and calculate the data.
Here are my four classes in the order; Driver, Entity, Super, Subs:
public static final String INPUT_FILE = "baseballTeam.txt";
public static void main(String[] args) {
BaseballTeam team = new BaseballTeam();
Scanner inFile = null;
try {
inFile = new Scanner(new File(INPUT_FILE));
team.loadTeam(inFile);
team.outputTeam();
} catch (FileNotFoundException e) {
System.out.println("File " + INPUT_FILE + " Not Found.");
System.exit(1);
}
}
}
public class BaseballTeam {
private String name;
private Player[] roster = new Player[25];
Player pitcher = new Pitcher();
Player batter = new Batter();
BaseballTeam() {
name = "";
}
public String getName() {
return name;
}
public void setName(String aName) {
name = aName;
}
public void loadTeam(Scanner input) {
name = input.nextLine();
for (int i = 0; i < roster.length; i++) {
if (i <= 9) {
roster[i] = new Pitcher();
}
else if ((i > 9) && (i <= 19)) {
roster[i] = new Batter();
}
else if (i > 19) {
roster[i] = new Player();
}
roster[i].loadData(input);
roster[i].generateDisplayString();
//System.out.println(roster[i].generateDisplayString()); //used sout to test for correct data
}
}
public void outputTeam() {
if ((pitcher instanceof Player) && (batter instanceof Player)) {
for (int i = 0; i < roster.length; i++) {
System.out.println(roster[i].generateDisplayString());
}
}
//How do I go about doing calculates?
public int calculateTeamWins() {
if ((pitcher instanceof ) && (batter instanceof Batter)) {
}
return 0;
}
public int calculateTeamSaves() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
public double calculateTeamERA() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
public double calculateTeamWHIP() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
public double calculateTeamBattingAverage() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
public int calculateTeamHomeRuns() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
public int calculateTeamRBI() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
public int calculateStolenBases() {
if ((pitcher instanceof Pitcher) && (batter instanceof Batter)) {
}
return 0;
}
}
public class Player {
protected String name;
protected String position;
Player(){
name = "";
position = "";
}
public String getName() {
return name;
}
public void setName(String aName) {
name = aName;
}
public String getPosition() {
return position;
}
public void setPosition(String aPosition) {
position = aPosition;
}
public void loadData(Scanner input){
do {
name = input.nextLine();
} while (name.equals(""));
position = input.next();
//System.out.println(generateDisplayString());
}
public String generateDisplayString(){
return "Name: " + name + ", Position:" + position;
}
}
public class Pitcher extends Player {
private int wins;
private int saves;
private int inningsPitched;
private int earnedRuns;
private int hits;
private int walks;
private double ERA;
private double WHIP;
Pitcher() {
super();
wins = 0;
saves = 0;
inningsPitched = 0;
earnedRuns = 0;
hits = 0;
walks = 0;
}
public int getWins() {
return wins;
}
public void setWins(int aWins) {
wins = aWins;
}
public int getSaves() {
return saves;
}
public void setSaves(int aSaves) {
saves = aSaves;
}
public int getInningsPitched() {
return inningsPitched;
}
public void setInningsPitched(int aInningsPitched) {
inningsPitched = aInningsPitched;
}
public int getEarnedRuns() {
return earnedRuns;
}
public void setEarnedRuns(int aEarnedRuns) {
earnedRuns = aEarnedRuns;
}
public int getHits() {
return hits;
}
public void setHits(int aHits) {
hits = aHits;
}
public int getWalks() {
return walks;
}
public void setWalks(int aWalks) {
walks = aWalks;
}
#Override
public void loadData(Scanner input) {
super.loadData(input);
wins = input.nextInt();
saves = input.nextInt();
inningsPitched = input.nextInt();
earnedRuns = input.nextInt();
hits = input.nextInt();
walks = input.nextInt();
}
#Override
public String generateDisplayString() {
calculateERA();
calculateWHIP();
return String.format(super.generateDisplayString() + ", Wins:%1d, Saves:%1d,"
+ " ERA:%1.2f, WHIP:%1.3f ", wins, saves, ERA, WHIP);
}
public double calculateERA() {
try {
ERA = ((double)(earnedRuns * 9) / inningsPitched);
} catch (ArithmeticException e) {
ERA = 0;
}
return ERA;
}
public double calculateWHIP() {
try {
WHIP = ((double)(walks + hits) / inningsPitched);
} catch (ArithmeticException e) {
WHIP = 0;
}
return WHIP;
}
}
public class Batter extends Player {
private int atBats;
private int hits;
private int homeRuns;
private int rbi;
private int stolenBases;
private double batAvg;
Batter() {
super();
atBats = 0;
hits = 0;
homeRuns = 0;
rbi = 0;
stolenBases = 0;
}
public int getAtBats() {
return atBats;
}
public void setAtBats(int aAtBats) {
atBats = aAtBats;
}
public int getHits() {
return hits;
}
public void setHits(int aHits) {
hits = aHits;
}
public int getHomeRuns() {
return homeRuns;
}
public void setHomeRuns(int aHomeRuns) {
homeRuns = aHomeRuns;
}
public int getRbi() {
return rbi;
}
public void setRbi(int aRbi) {
rbi = aRbi;
}
public int getStolenBases() {
return stolenBases;
}
public void setStolenBases(int aStolenBases) {
stolenBases = aStolenBases;
}
#Override
public void loadData(Scanner input) {
super.loadData(input);
atBats = input.nextInt();
hits = input.nextInt();
homeRuns = input.nextInt();
rbi = input.nextInt();
stolenBases = input.nextInt();
}
#Override
public String generateDisplayString() {
calculateBattingAverage();
return String.format(super.generateDisplayString() +
", Batting Average:%1.3f, Home Runs:%1d, RBI:%1d, Stolen Bases:%1d"
, batAvg, homeRuns, rbi, stolenBases);
}
public double calculateBattingAverage() {
try{
batAvg = ((double)hits/atBats);
} catch (ArithmeticException e){
batAvg = 0;
}
return batAvg;
}
}
Also, its probably easy to tell I'm still fairly new here, because I just ran all my classes together in with the code sample and I can't figure out to add the gaps, so feel free to edit if need be.
The typical usage of instanceof in the type of scenario you're describing would be
if (foo instanceof FooSubclass) {
FooSubclass fooSub = (FooSubclass) foo;
//foo and fooSub now are references to the same object, and you can use fooSub to call methods on the subclass
} else if (foo instanceof OtherSubclass) {
OtherSubclass otherSub = (OtherSubclass) foo;
//you can now use otherSub to call subclass-specific methods on foo
}
This is called "casting" or "explicitly casting" foo to FooSubclass.
the concept to call the methods of your subclasses is called polymorphism.
In your runtime the most specific available method is called provided that the method names are the same.
so you can
Superclass class = new Subclass();
class.method();
and the method provided that overwrites the method in Superclass will be called, even if it's defined in the Subclass.
Sorry for my english, I hope that helps a little bit ;-)
I want to do a sum for all over a Collection of numbers. But I want to indicate the return number type. For example I want to do the sum of a double collection, but I want to get back an Integer.
I want to have something like this SumAggregator. Here is the code I develop, but I have a Cast problem.
public class SumAggregator<N1 extends Number, N2 extends Number> {
public SumAggregator() {
}
public N2 sum(Collection<? extends N1> list){
Double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return (N2) sum;
}
}
If I want to do SumAggregator<Double, Double> I don't have any problem. But if I want to do SumAggregator<Double, Integer>, once I run I get the following exception:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
Any idea of how to solve this?
Not exactly what you wanted but you could do something like:
interface DoubleConverter<N extends Number) {
N2 convert(double d);
}
And add a constructor to your SumAggregator:
private final DoubleConverter<N2> converter;
public SumAggregator(DoubleConverter<N2> converter) {
this.converter = converter;
}
And your method would look like:
public N2 sum(Collection<? extends N1> list){
double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return converter.convert(sum);
}
finally, you would create one with:
SumAggregator<Double, Integer> a = new SumAggregator<> (new DoubleConverter<Integer>() {
public Integer convert(double d) { return (int) d; }
});
Finally, you could add some helper methods in the DoubleConverter interface:
DoubleConverter<Integer> INTEGER = new DoubleConverter<Integer>() {
public Integer convert(double d) { return (int) d; }
}
so the calling code can use:
SumAggregator<Double, Integer> a = new SumAggregator<> (DoubleConverter.INTEGER);
This is the solution I choose:
public class SumAggregator<N1 extends Number, N2 extends Number> {
private final NumberConverter<N2> converter;
public SumAggregator(NumberConverter<N2> converter) {
this.converter = converter;
}
public N2 sum(Collection<? extends N1> list){
double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return converter.convert(sum);
}
}
And then:
public interface NumberConverter<N2> {
N2 convert(Number d);
NumberConverter<Short> SHORT = new NumberConverter<Short>() {
public Short convert(Number d) {
return d.shortValue();
}
};
NumberConverter<Integer> INTEGER = new NumberConverter<Integer>() {
public Integer convert(Number d) {
return d.intValue();
}
};
NumberConverter<Double> DOUBLE = new NumberConverter<Double>() {
public Double convert(Number d) {
return d.doubleValue();
}
};
NumberConverter<Float> FLOAT = new NumberConverter<Float>() {
public Float convert(Number d) {
return d.floatValue();
}
};
NumberConverter<Long> LONG = new NumberConverter<Long>() {
public Long convert(Number d) {
return d.longValue();
}
};
}