How to re-use value in different functions? - java

I am programming a Study in MotiveWave, a program used for (day)trading. The study is its own class. (info about MotiveWave's SDK found here: https://www.motivewave.com/sdk/javadoc/overview-summary.html)
public class L_V2 extends com.motivewave.platform.sdk.study.Study
My study uses 2 different timeframes: the 1 hour and the 4 hour bars. Both are calculated in a different function. Otherwise formulated: both use a different dataseries, as shown in the code below.
I have two values, being calculated on the 4 hour timeframe, called 'ma9' and 'ma11' that I would like to use in an 'if'-statement on the 1 hour timeframe.
This is the code for the 4 hour timeframe. It simply calculates 2 moving averages
#Override
protected void calculateValues(DataContext ctx)
{
int maPeriodTF2 = getSettings().getInteger(MA_PERIOD_TF2);
int ma2PeriodTF2 = getSettings().getInteger(MA2_PERIOD_TF2);
//Object maInput = getSettings().getInput(MA_INPUT, Enums.BarInput.CLOSE);
BarSize barSizeTF2 = getSettings().getBarSize(MA_BARSIZE_TF2);
DataSeries series2 = ctx.getDataSeries(barSizeTF2);
StudyHeader header = getHeader();
boolean updates = getSettings().isBarUpdates() || (header != null && header.requiresBarUpdates());
// Calculate Moving Average for the Secondary Data Series
for(int i = 1; i < series2.size(); i++) {
if (series2.isComplete(i)) continue;
if (!updates && !series2.isBarComplete(i)) continue;
// MA TF2
Double ma9 = series2.ma(getSettings().getMAMethod(MA_METHOD_TF2), i, maPeriodTF2, getSettings().getInput(MA_INPUT_TF2));
Double ma11 = series2.ma(getSettings().getMAMethod(MA2_METHOD_TF2), i, ma2PeriodTF2, getSettings().getInput(MA2_INPUT_TF2));
series2.setDouble(i, Values.MA9_H4, ma9);
series2.setDouble(i, Values.MA11_H4, ma11);
}
// Invoke the parent method to run the "calculate" method below for the primary (chart) data series
super.calculateValues(ctx);
I would now like to use those 2 values, 'ma9' and 'ma11' in another function, on the 1 hour timeframe:
#Override
protected void calculate(int index, DataContext ctx)
DataSeries series=ctx.getDataSeries();
if (ma9 < ma11 && other conditions)
{ctx.signal(index, Signals.YOU_SHOULD_BUY, "This would be my buying signal", series.getClose(index));
}
How can I export the ma9 and the ma11 so they become 'global' and I can re-use them in this other function ?

Basically, the idea is to store somewhere the values or just pass them appropriately after being computed.
There is a java pattern based on singleton that allow you to store/retrieve values inside a class (using a collection : HashMap). Any values could be added,retried in any classes based on predefined (key,value) using the construction Singelton.getInstance() with HashMap standard operation (put, get).
Maybe this example could be useful.
import java.util.Hashtable;
class Singleton extends Hashtable<String, Object> {
private static final long serialVersionUID = 1L;
private static Singleton one_instance = null;
private Singleton() {
};
public static Singleton getInstance() {
one_instance = (one_instance == null) ? new Singleton() : one_instance;
return one_instance;
}
}
import java.util.Random;
public class Reuse {
public static void main(String[] args) {
Reuse r = new Reuse();
Compute c = r.new Compute();
Singleton.getInstance().put("r1", c.getRandom());
Singleton.getInstance().put("r2", c.getRandom());
Singleton.getInstance().put("n", c.getName());
System.out.println(Singleton.getInstance().get("r1"));//print random_number_1
System.out.println(Singleton.getInstance().get("r2"));//print random_number_2
System.out.println(Singleton.getInstance().get("n"));// print name (value for key n)
}
class Compute
{
public Double getRandom()
{
return new Random().nextDouble();
}
public String getName()
{
return "name";
}
}
}

Related

Generic Supplier for n Getters Across Collection

I have a collection of Java objects where I want to run a single function across multiple values I might find in some of the object's member variables. I'm looking for a nice way to pass in which getter should be used so I can have one method do all that work. I was thinking about something like a Supplier, but that would mean I have to have one per instance of the class. Here's an example of what I'm trying to do (only I would like to do this without the if statement or with potentially n getters a switch statement:
import java.util.ArrayList;
import java.util.List;
public class TestSupplier {
private int varA;
private int varB;
public TestSupplier(int varA, int varB) {
this.varA = varA;
this.varB = varB;
}
public int getA() {
return this.varA;
}
public int getB() {
return this.varB;
}
public static void main(String[] args) {
List<TestSupplier> testList = new ArrayList<>();
testList.add(new TestSupplier(1, 11));
testList.add(new TestSupplier(2, 22));
// Can I pass something like a generic supplier instead of a bool?
TestSupplier.someCollectorFunction(testList, true);
TestSupplier.someCollectorFunction(testList, false);
}
public static void someCollectorFunction(List<TestSupplier> list, boolean isA /* what if I want more than one getter*/) {
int sum = 0;
for (TestSupplier obj: list) {
// This is where I wish I could have a generic supplier or something
if (isA) {
sum = sum + obj.getA();
}
else {
sum = sum + obj.getB();
}
}
System.out.println("I have a sum: " + sum);
}
}
Is there something is Java's functional API that would let me do this?
It sounds like what you want is
ToIntFunction<TestSupplier> fn = isA ? TestSupplier::getA : TestSupplier::getB;
for (TestSupplier obj: list) {
sum += fn.applyAsInt(obj);
}
It's up to you whether you consider that an improvement.
You could also pass in the ToIntFunction instead of the boolean, passing in TestSupplier::getA instead of true etc.

Java - Inheritance regarding constructors

So, I'm trying to practice my java skills by applying it to some math homework and making a frequency distribution chart using inheritance. In my head, I envision it as a frequency distribution (parent class = FreqDist) that can have multiple "MyStatClasses" (in the form of the MyStatClass array). Each FreqDist has variables that span across all MyStatClasses which is why I put them in the parent class. However, when I call the MyStatClass constructor, my program gets a StackOverflowError. I think this is because the super(s, i) line calls back to the FreqDist constructor and starts over, causing an infinite loop. Assuming this is the case, how would I fix this?
Ideally, I'd like to access my MyStatClass array and grab values that only apply to that MyStatClass, but I cannot get it to work.
public class FreqDist {
private MyStatClass[] freqClasses;
private double[] dblValuesArray;
private int intNumberOfClasses;
private double dblMax;
private double dblMin;
private int intClassWidth;
public FreqDist(String strValues, int intNumOfClasses) {
System.out.println("This is the beginning of the FreqDist constructor...");
dblValuesArray = getDoubleValues(strValues);
intNumberOfClasses = intNumOfClasses;
dblMin = dblValuesArray[0];
dblMax = dblValuesArray[dblValuesArray.length - 1];
intClassWidth = (int)Math.ceil((dblMax - dblMin) / intNumberOfClasses);
freqClasses = new MyStatClass[intNumberOfClasses];
for (int x = 0; x < freqClasses.length; x++) {
freqClasses[x] = new MyStatClass(strValues, intNumOfClasses);
}
}
public double[] getDoubleValues(String strValues) {
String[] strValuesArray = strValues.trim().split(" ");
dblValuesArray = new double[strValuesArray.length];
for (int x = 0; x < strValuesArray.length; x++) {
dblValuesArray[x] = Double.parseDouble(strValuesArray[x]);
}
Arrays.sort(dblValuesArray);
return dblValuesArray;
}
public int getNumberOfClasses() {
return intNumberOfClasses;
}
public double getMin() {
return dblMin;
}
public double getMax() {
return dblMax;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("What are the values? ");
String values = scan.nextLine();
System.out.print("How many classes? ");
int classes = scan.nextInt();
FreqDist fd = new FreqDist(values, classes);
}
}
public class MyStatClass extends FreqDist {
public MyStatClass(String s, int i) {
super(s, i);
}
}
Ok so this is mostly an issue with a flaw in your design.
From what I understand FreqDist is a class that should contain an array of MyStatClass. You want them to have the same properties so you make MyStatClass extend FreqDist. However when you call FreqDist it MyStatClass which Calls a new MyStatClass over and over and over.
One way to solve this is to create a new class that has the shared properties you want FreqDist and MyStatClass to have, and have those two classes inherit from said class. Then create separate constructors for FreqDist and MyStatClass.
A parent type should never refer to its own subtypes, as yours does. Her the parent initializes subtype instances, which require that each initialize the parent type, which initializes subtype instances, which initialize their parent type, which initializes... KABLOOEY!

How do I pull value from method designated with "this."

I have information like this:
xxx 0 1 2 ...
Name Fred0 Fred1 Fred2
Stamina 2 6 7
Intel 5 4 1
Heart 4 8 2
Speed 5 3 6
So, I was informed previously that creating a 2D ArrayList to store something like this is "archaic" and was provided with a different way to set my code up. The reason I was using ArrayList<> is because I want to be able to generate new racers as needed, rather than designating an array to a size. If I could just use a simple array this would have been done a week ago. Now I've been screwing with it for a week and I still don't get how it works.
public class test {
public String name;
private int stamina;
private int heart;
private int intel;
private int speed;
public ArrayList<String> racers = new ArrayList<String>();
private void racerInfo(String name) {
this.name = name;
this.stamina = (int) Math.floor(Math.random()*10);
this.heart = (int) Math.floor(Math.random()*10);
this.intel = (int) Math.floor(Math.random()*10);
this.speed = (int) Math.floor(Math.random()*10);
}
public void generate() {
for ( int i=0; i<=10; i++) {
String name = "Fred" + i;
System.out.println(name);
racerInfo(name);
racers.add(name);
}
}
public int getStamina() {
return this.stamina;
}
public int getHeart() {
return this.heart;
}
public int getIntel() {
return this.intel;
}
public int getSpeed() {
return this.speed;
}
}
public class main {
public static test test = new test();
public static void main(String[] args) {
test.generate();
//Put stuff here to pull stamina of Fred2 for example.
}
}
Now, in the main class. How would I do something that should be relatively simple like pulling the Stamina value for Fred2.
I've been following the exact directions I've been given by others here to write most of this code. But at this time, I'm getting to the point of just re-writing it all so that each stat (name, stamina, intel, speed, etc.) is just logged as a separate ArrayList<>. But I can't figure out how to make a 2D ArrayList containing the original ArrayLists ie.
ArrayList<String> name = new ArrayList<String>();
ArrayList<Integer> stamina = new ArrayList<Integer>();
ArrayList<ArrayList<Object>> arrayOfArray = new ArrayList<ArrayList<Object>>();
Yes, I know the arrayOfArray is probably done wrong, but, again, I just get told it's Archaic and nobody'll tell me how I can do it right so I can just go. arrayOfArray.get(2,1) and pull information that I want/need.
Sorry for the information overload here. but I'm trying to just find the best possible solution for what I want to do. If you can tell me how to correctly pull off either way I will be eternally grateful you you and all of your descendants.
First of you should refactor your class test to class Racer, which is a meaningful name and follows the convention to start classnames with an uppercase letter. Furthermore you should add Stamina, Intel, Heart and Speed to the constructor:
public Racer(String name, int stamina, int intel, int heart, int speed) {
this.name = name;
this.stamina = stamina;
this.intel = intel;
this.heart = heart;
this.speed = speed;
}
Now you can create your racer as following:
Racer fred2 = new Racer("Fred2", 7, 1, 2, 6);
You can store your values in a HashMap. HashMap is a collection consisting of key-value pairs. For the key you can use a string (the name of the racer) and as value you take an instance of your class Racer:
HashMap<String, Racer>() racerMap = new HashMap<>();
racerMap.put("Fred2", fred2);
This you can do in a for-loop for all of your racers. Now you can get the racer objects from your HashMap by calling the getMethod and putting the name as parameter in it. This will return an object of class Racer and you can call the getter methods on this object:
racerMap.get("Fred2").getSpeed();
or
racerMap.get("Fred2").getIntel();
Edit: I just saw your generate method. This method should return the HashMap of racers. In your main method you create a new HashMap:
HashMap<String, Racer> racerMap = generate();
Now you can use the map as described above.

Get and set methods not changing the array

I have extended a class in hope to store a global array (make the array within the class be seen by another object) by using the set1sub(sub.local) method
public class BattleShipsClient extends ShipLocations implements Runnable, BattleShipConstants
{
BattleShipsClient()
{
}
public void placeBoard(int player) throws IOException// this is only called once and not updated when clicked again
{
while(getLocations())
{
while(isWaiting())//true
{
toServer.writeInt(player);
int row = getRowSelected();
int col = getColumnSelected();
int choice=Integer.parseInt(JOptionPane.showInputDialog("Please 1 for a sub, 2 for a battleship and 3 for a destroyer"));
clickCount ++;
if(clickCount >2)
{
setLocation(false);
continueToPlay=true;
}
if (choice ==1 &&sub.placed==false)
{
String orientation =JOptionPane.showInputDialog("please enter your orientations");
if(orientation.equalsIgnoreCase("h"))
{
//row os the same
//column number will be sent, then plus one on the other side
sub.local = new int[2][2];
sub.local[0][0] =row;
sub.local[0][1]=col;
sub.local[1][0]=row;
sub.local[1][1] =col+1;
toServer.writeInt(row);
toServer.writeInt(col);
toServer.writeChar('s');
sub.placed=true;
setp1sub(sub.local);
/*setp1sub(new int[][]{{row,col},
{row,col+1}});*/
grid[row][col+1].setToken(getMyToken());
}
I then have a ship Locations class however when i create a new object of the ship locations class and try to read this array it always is set to [[0, 0], [0, 0]], ive tried making it static and atomic
public class ShipLocations {
int [][] p1sub;
public ShipLocations()
{
p1sub = new int[2][2];
}
public int[][] getp1sub()
{
return p1sub;
}
public void setp1sub(int[][] local) {
for (int i = 0;i <local.length;i++)
{
for(int j = 0;j<local.length;j++)
{
p1sub [i][j]= local[i][j];
}
}
}
}
Whenever you create a new instance of ShipLocations(or a subclass) the constructor is called, which in your case, reinitializes the p1sub array.
In your design, you are overusing inheritance. You should not inherit from a class just to use its methods and variables.
To store a global variable in a class:
public class ShipLocations {
static int [][] p1sub;
static{
p1sub = new int[2][2];
}
public static void setp1sub(...){...}
public static int[][] getp1sub(){...}
}
And then use it by class name instead of creating instances:
int [][] x = ShipLocations.getp1sub();
Though the use of global variables shoud be avoided when possible. It is considered bad design and might be a problem when reusing the code.
The correct way of doing this is to have the ShipLocations object as a local variable in BattleShipsClient and set it when initializing new instance. You will then first create a common ShipLocation object and hand it to every client that should see the same array.

hashmap custom class key && object saving/loading

Been working on a project for a while now and I've come across a few different complications and solutions that don't seem to pan out together.
final public class place implements Serializable {
private static final long serialVersionUID = -8851896330953573877L;
String world;
Double X;
Double Y;
Double Z;
}
HashMap<place, Long> blockmap = new HashMap<place, Long>(); // does not work
HashMap<Location, Long> blockmap = new HashMap<Location, Long>(); //works
First, my hashmap is a hashmap containing the time an item was placed (or added) to the world. place is a 'class place {}' containing String world, double x, double y, double z; The problem i've had with this, is that it doesn't work with hashmaps. I can store a new hash key using it, but i cant call to get its value. Using Location instead fixes this problem (hashmap) and works flawlessly.
public void SetBlock(Block block) {
Location loc = new Location(null, block.getLocation().getX(),block.getLocation().getY(),block.getLocation().getZ());
//...
Long time = (long) (System.currentTimeMillis() / 60000);
//...
if (blockmap.containsKey(loc)) {
blockmap.remove(loc);
blockmap.put(loc, time);
//System.out.println("MyLeveler: Block Existed, Updated");
} else {
blockmap.put(loc, time);
//System.out.println("MyLeveler: Block added to " + loc.getX() + ", " + loc.getY() + ", " + loc.getZ());
//System.out.println("MyLeveler: total blocks saved: " + blockmap.size());
}
}
This works without error. Now, for the purpose, this data has to be saved and reloaded when the plugin is disabled, and enabled. To do this, i created a new java class file with a save/load feature.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SLAPI {
public static void save(Object obj,String path) throws Exception
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
oos.writeObject(obj);
oos.flush();
oos.close();
}
public static Object load(String path) throws Exception
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
Object result = ois.readObject();
ois.close();
return result;
}
}
I typically get "notserializable" errors. Using 'implements Serializable' and ois.defaultReadObject() or oos.defaultWriteObject() which checks the serial on the file results in a clean save/load only when the object is EMPTY! When it contains data, i constantly get "java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException"
This is clearly a problem! One of the recommendations here: ArrayList custom class as HashMap key failed to produce any better results. In fact, creating a custom class was my first issue to begin with >.>
So i guess the questions are:
1) What would i have to alter to use the custom class as a key (and work properly)
2) Why doesn't it recognize that i'm setting it as a serializable class/function/java class
3) Why does it work with an empty hashmap, but not with a filled hashmap?
Basically you need to override hashCode() and equals() in place. Presumably Location already overrides these methods.
Those are the methods that HashMap uses to first narrow down the list of candidate keys very quickly (using the hash code) and then check them for equality (by calling equals).
It's not clear what the serializable problem is - my guess is that although place is serializable, Location isn't. If you could post a short but complete problem demonstrating the problem, that would really help. (It would also be a good idea to start following Java naming conventions, and making your fields private...)
EDIT: Here's an example of the Place class with hash code and equality. Note that I've made it immutable for the sake of avoiding the values changing after it's used as a key in a hash map - I don't know offhand how well that works with serialization, but hopefully it's okay:
public final class Place implements Serializable {
private static final long serialVersionUID = -8851896330953573877L;
private final String world;
// Do you definitely want Double here rather than double?
private final Double x;
private final Double y;
private final Double z;
public Place(String world, Double x, Double y, Double z) {
this.world = world;
this.x = x;
this.y = y;
this.z = z;
}
#Override public int hashCode() {
int hash = 17;
hash = hash * 31 + (world == null ? 0 : world.hashCode());
hash = hash * 31 + (x == null ? 0 : x.hashCode());
hash = hash * 31 + (y == null ? 0 : y.hashCode());
hash = hash * 31 + (z == null ? 0 : z.hashCode());
return hash;
}
#Override public boolean equals(Object other) {
if (!(other instanceof Place)) {
return false;
}
Place p = (Place) other;
// Consider using Guava's "Objects" class to make this simpler
return equalsHelper(world, p.world) &&
equalsHelper(x, p.x) &&
equalsHelper(y, p.y) &&
equalsHelper(z, p.z);
}
private static boolean equalsHelper(Object a, Object b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
return a.equals(b);
}
// TODO: Add getters?
}
It's worth noting that this will be comparing Double values for equality, which is almost always a bad idea... but you can't really give a tolerance in something like equals. So long as the values are exactly the same when you come to look them up, it should work fine.

Categories