I have a problem. I have the following class:
public class Candlestick {
private double ma5;
private double ma10;
private double ma17;
public void setMA5(double value) {
this.ma5 = value;
}
public void setMA10(double value) {
this.ma10 = value;
}
public void setMA17(double value) {
this.ma17 = value;
}
}
Then I also have the following array:
public static List<Integer> mas = List.of(5, 10, 17);
Now in my code I have a for loop that loops through the mas list, like this:
Candlestick candlestick = new Candlestick();
for (int ma : mas) {
// UPDATE THE CORRECT MA VALUE IN THE CANDLESTICK CLASS
candlestick.setMA ????
}
But I need to update the attribute of the class I am currently on in the loop. How can I prorammatically build up the setMA() function?
You can utilize Java Reflection.
Candlestick candlestick = new Candlestick();
for (int ma : mas) {
Method setMaMethod = Candlestick.class.getDeclaredMethod("setMA" + ma, double.class);
setMaMethod.invoke(candlestick, 1.0);
}
This code invokes setMA* passing 1.0 as a function argument.
The most common approach to acquire methods depending on a variable would be to use reflection - the getMethod(String name, Class<?>... parameterTypes) method for example.
However, for your example I think a Map with a Integer key would be more suitable than every reflection.
That would leave us with the following Candlestick class (main method just for testing):
import java.util.Map;
import java.util.TreeMap;
public class Candlestick {
private Map<Integer, Double> masses;
public Candlestick()
{
masses = new TreeMap<>();
}
public Map<Integer, Double> getMasses() {
return masses;
}
public Double getMassValue(int key)
{
return masses.get(key);
}
public void setMassValue(int key, double value)
{
masses.put(key, value);
}
public static void main(String[] args)
{
Candlestick candlestick = new Candlestick();
candlestick.setMassValue(5, 13.37);
System.out.println(candlestick.getMassValue(5));
}
}
This would also allow you to easily iterate over the masses (or whatever MA is supposed to mean, that's why someone should use proper variable names ;)).
Related
I try to write recursive function which gets an array of flights and returns all the possible paths from source country to dest country.
The function signature in Java:
List<List<String>> printAllPathsUtil(String src, String d,List<Flight> localPathList)
every object of type Flight contain 2 features from and to.
I succeed to write the below code and its run successfuly,but I sent to the function one more parameter : String help -who store the source country.
public List<List<String>> printAllPathsUtil(**String help**,String src, String d,List<Flight> localPathList)
I would appreciate it if someone could please find a way how to use the function without the extra parameter,and show in the code.
Note:I implemented the classes in a minimal way just to have parameters to send to the function, therefore there is no get and set in the classes.
import java.util.ArrayList;
import java.util.List;
public class flligth {
public static void main(String args[]) {
Flight f1 = new Flight("ISRAEL","ROMANIA");
Flight f2 = new Flight("ISRAEL","HOLAND");
Flight f3 = new Flight("ISRAEL","LONDON");
Flight f4 = new Flight("ISRAEL","U.S.A");
Flight f5 = new Flight("HOLAND","LONDON");
Flight f6 = new Flight("LONDON","ROMANIA");
all_flight all_f=new all_flight(6);
all_f.addEdge(f1);f1.print();
all_f.addEdge(f2);f2.print();
all_f.addEdge(f3);f3.print();
all_f.addEdge(f4);f4.print();
all_f.addEdge(f5);f5.print();
all_f.addEdge(f6);f6.print();
List <Flight> localPathList=new ArrayList<>();
all_f.printAllPathsUtil("ISRAEL","ISRAEL","ROMANIA",localPathList);
}
}
class Flight{
String from;
String to;
public Flight(String from ,String to){
this.from=from;
this.to=to;
}
public void print()
{
System.out.print(from+" ");
System.out.println(to);
}
}
class all_flight{
static int current=0;
// adjacency list
public ArrayList<Flight> f;
int index;
// Constructor
public all_flight(int index){
this.index=index;
initFlight();
}
// utility method to initialise
// f list
private void initFlight()
{
f = new ArrayList<Flight>();
}
// add edge from u to v
public void addEdge( Flight path)
{
// Add to list.
f.add(path);
}
public List<List<String>> printAllPathsUtil(String help,String src, String d,List<Flight> localPathList)
{
Flight now = f.stream()
.filter(a -> a.from.equals(src)).findFirst()
.orElse(new Flight("no from","no to"));
if(now.from.equals("no from")){
f.remove(0);
localPathList.clear();
if(!(f.isEmpty())){
return printAllPathsUtil(help,f.get(0).from,d,localPathList);
}
return null;
}
localPathList.add(now);
if(localPathList.get(localPathList.size()-1).to.equals(d)
&& localPathList.get(0).from.equals(help)){
System.out.println("the path is :");
printPath(localPathList);
}
return printAllPathsUtil(help,now.to,d,localPathList);
}
private static void printPath(List<Flight> path)
{
for(Flight v : path)
{
v.print();
}
System.out.println();
}
}
Whenever you invoke the printAllPathsUtil() function, you're passing the same value of help each time. Since the property stays constant for each recursive call, you can simply remove it from the parameters.
Instead, you can create a class attribute origin, and replace the usage of help in the function with self.origin.
If localPathList is empty, then help is src. Otherwise, it's localPathList.get(0).from.
(for some context) My real world problem is that I have many Text objects that depending on conditions will need the method text.setText("sometext") to be executed. (Im creating a calendar that as the months change, so does the first day of the month, which in turn causes the dates (1,31) to change where they appear on the calendar interface i created .
My approach was to create Text objects, add them to a HashMap. Then, depending on where the first day of the month is, call the appropriate Text objects from the HashMap and run a method from within the Text class text.setText("sometext")
i haven't added the actual code, because 99% is irrelevant and would probably just confuse issues but this code should illustrate what I'm trying to achieve. `public class Test {
public static void main(String[] args) {
ExampleCLass object1 = new ExampleCLass("object1");
ExampleCLass object2 = new ExampleCLass("object2");
HashMap<Integer, Object> hashMap = new HashMap<>();
//if some condition has been met
for(Object object : hashMap){
object.printname();
}
}
}`
public class ExampleCLass {
private final String name;
public ExampleCLass(String name) {
this.name = name;
}
public void printName(){
System.out.println(this.name);
}
}
any tips on getting this to work, or suggestions of a different/better approach would be massively appreciated.
Getting your code, which didn't even compile, to work.
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
new HashMapTest().test();
}
public void test() {
HashMap<Integer, ExampleClass> hashMap = new HashMap<>();
ExampleClass object1 = new ExampleClass("object1");
hashMap.put(1, object1);
ExampleClass object2 = new ExampleClass("object2");
hashMap.put(2, object2);
// if some condition has been met
Set<Integer> hashSet = hashMap.keySet();
Iterator<Integer> iter = hashSet.iterator();
while (iter.hasNext()) {
Integer key = iter.next();
ExampleClass ec = hashMap.get(key);
System.out.println(ec.printName());
}
}
public class ExampleClass {
private final String name;
public ExampleClass(String name) {
this.name = name;
}
public String printName() {
return this.name;
}
}
}
Lambda is used here, but when ::new is used, the following parameters are populated into the constructor:
#FunctionalInterface
interface Lambdademo1<T> {
T test(String s);
}
class Test {
public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
Apple i = lambdademo1.test(s);
System.out.println(i.getColor());
}
public static void main(String args[]){
test2(Apple::new,"hehehe");
}
}
Output:
hehehe
UPDATE:
class test {
public static void main(String args[]) {
test1((String s) -> new Integer(1), "hehehe");
test1(Integer::new, "hehehe"); //It's wrong
test2(Apple::new,"hehehe");
test3(Apple1::new,"hehehe"); //Compile error
// I think XXX::new is equivalen to new XXX() but here shoe it's not
}
public static void test1(Lambdademo1<Integer> lambdademo1, String s) {
Integer i = lambdademo1.test(s);
System.out.println(i);
}
public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
Apple i = lambdademo1.test(s);
System.out.println(i.getColor());
}
public static void test3(Lambdademo1<Apple1> lambdademo1, String s) {
Apple1 i = lambdademo1.test(s);
System.out.println(i.getColor());
}
}
The Apple1 class:
class Apple1 {
private String color;
// getter and setter
}
The Apple class:
class Apple {
private String color;
public Apple(String color) {
this.color = color;
}
// getter and setter
}
Original answer
Apple::new can (and does) refer to a constructor Apple(String) because it follows the contract of T test(String s) - (String string) -> new Apple(string); or Apple:new
Apparently, that constructor sets the value for the color field since the getter returns the value you passed to the constructor.
test2(Apple::new,"hehehe");
is equivalent to
System.out.println(new Apple("hehehe").getColor());
Update
Let's discuss each line in detail to make it clear.
1.
test1((String s) -> new Integer(1), "hehehe");
You are taking a String s, not using it, and returning a constant new Integer(1) or simply 1.
We might rewrite it to
test1(s -> 1,"hehehe" );
2.
test1(Integer::new, "hehehe");
It's not wrong. It's absolutely compilable line. There is a constructor Integer(String s) that converts the given String to an int using Integer.parseInt(String).
Since "hehehe" isn't a parsable int, you will get a NumberFormatException, but that's a runtime issue.
3.
It's fine, and I have explained it in the original answer above.
4.
test3(Apple1::new,"hehehe");
You haven't defined any constructors for Apple1, so we have the no-arguments one by default. Since it doesn't take a String, we can't use it to represent Lambdademo1#test.
Writing a lambda will make it compile, though.
test3(s -> new Apple1(),"hehehe");
I think XXX::new is equivalent to new XXX() but here it's not.
It depends on context. XXX::new always refers to a constructor. What constructor? We don't know it until we see the context.
Examine an example where Apple::new points at 3 different constructors.
class Apple {
public Apple() {}
public Apple(Integer i) {}
public Apple(String s) {}
public static void main(String[] args) {
Supplier<Apple> a = Apple::new;
Function<Integer, Apple> b = Apple::new;
Function<String, Apple> c = Apple::new;
}
}
I encountered problem I am unable to solve. Thing is, my TableView is already populated and I need for cells that match my criteria to set value zero. I have variable korZemljiste and if my condition is fullfilled cells in column colOsnovica need to be set to value 0.00.
Here is what I tried:
if (korZemljiste < 10000)
{
tblTabela.getItems().stream().forEach((o)
-> {
colOsnovica.setCellFactory(TextFieldTableCell.forTableColumn());
colOsnovica.setOnEditCommit(
new EventHandler<CellEditEvent<Nepokretnost, Number>>() {
#Override
public void handle(CellEditEvent<Nepokretnost, Number> t) {
((Nepokretnost) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setOsnovica(t.getNewValue());
}
});});}
Sorry, for ugly end of code, couldn't make to copy it properly.
This part I modified from Oracle example and I get error:
error: incompatible types: no instance(s) of type variable(s) S exist so that Callback<TableColumn<S,String>,TableCell<S,String>> conforms to Callback<TableColumn<Nepokretnost,Number>,TableCell<Nepokretnost,Number>>
colOsnovica.setCellFactory(TextFieldTableCell.forTableColumn());
where S is a type-variable:
S extends Object declared in method forTableColumn()
error: incompatible types: Number cannot be converted to double
).setOsnovica(t.getNewValue());
My TableView using <Nepokretnost, Number> form.
Note: I guess I don't need this example from Oracle site because I don't want to manually change contents of cell in column, I just want to set them to value 0.00.
Some easy solution anyone?
Thanks in advance.
For the first error, since your table column type is not a String, you cannot use the no-argument version of TextFieldTableCell.forTableColumn(). The underlying problem is that, to edit the cell, the text field provides a String and the data in the cell is a Number. You need to provide a converter, using the overloaded form of TextFieldTableCell.forTableColumn(...):
colOsnovica.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
For the second error, just replace t.getNewValue() (which returns a Number) with t.getNewValue().doubleValue() (which gets the double representation of the Number).
#james-d
Hm, my mistake. Class is simple, here it is:
package obracun;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
/**
*
* #author Dalibor
*/
public class Nepokretnost {
private final SimpleStringProperty tipNepokretnosti;
private final SimpleStringProperty zona;
private final SimpleStringProperty pravo;
private final SimpleDoubleProperty povrsina;
private final SimpleDoubleProperty amortizacija;
private final SimpleDoubleProperty osnovica;
private final SimpleDoubleProperty kredit;
private final SimpleDoubleProperty porez;
public Nepokretnost(String tipNepokretnosti, String zona, String pravo,
Double povrsina, double amortizacija, Double osnovica, Double kredit, Double porez) {
this.tipNepokretnosti = new SimpleStringProperty(tipNepokretnosti);
this.zona = new SimpleStringProperty(zona);
this.pravo = new SimpleStringProperty(pravo);
this.povrsina = new SimpleDoubleProperty(povrsina);
this.amortizacija = new SimpleDoubleProperty(amortizacija);
this.osnovica = new SimpleDoubleProperty(osnovica);
this.kredit = new SimpleDoubleProperty(kredit);
this.porez = new SimpleDoubleProperty(porez);
}
public String getTipNepokretnosti() {
return tipNepokretnosti.get();
}
public void setTipNepokretnosti(String tipNepokretnosti) {
this.tipNepokretnosti.set(tipNepokretnosti);
}
public String getZona() {
return zona.get();
}
public void setZona(String zona) {
this.zona.set(zona);
}
public String getPravo() {
return pravo.get();
}
public void setPravo(String pravo) {
this.pravo.set(pravo);
}
public double getPovrsina() {
return povrsina.get();
}
public void setPovrsina(double povrsina) {
this.povrsina.set(povrsina);
}
public double getAmortizacija() {
return amortizacija.get();
}
public void setAmortizacija(double amortizacija) {
this.amortizacija.set(amortizacija);
}
public double getOsnovica() {
return osnovica.get();
}
public void setOsnovica(double osnovica) {
this.osnovica.set(osnovica);
}
public double getKredit() {
return kredit.get();
}
public void setKredit(double kredit) {
this.kredit.set(kredit);
}
public double getPorez() {
return porez.get();
}
public void setPorez(double porez) {
this.porez.set(porez);
}
}
I didn't realized it is necessary to post class here. I had this application made before just in Swing. There I just changed contents of JTableView field. This is kinda different, thanks for help.
I posted and screenshot of app. On screenshot I already added elements in TableView I wanted. Code I posted in question is part of Calculate (Обрачун) button event handler. In this example calculation should change the contents of field Основица to 0.00.
The idea I'm going for is that I have a bunch of actions/functions that happen in our program. They're all predefined and separated into categories. So there might be a category for admin actions that then defines a bunch of static codes for actions that are in the admin actions category.
Since the categories and actions are fixed, they're all in static classes.
These static category classes all implement an interface, ICategory:
public static interface ICategory{
int getCateogory();
String getCategoryName();
String getFunctionName(int function);
}
Each of these static classes is added to a static Map:
private static Map<Integer, Class<? extends ICategory>> catMap = new HashMap<Integer, Class<? extends ICategory>>();
Basically there's an integer code associated with each category. What I'm trying to do is just made a human readable string that I can print out when I receive the category and action codes. What I would like to do is something like
ICategory whatever = catMap.get(catNumber);
System.out.println(whatever.getCategoryName());
System.out.println(whatever.getFunctionName(actionCode));
So catMap.get(catNumber) will actually return the proper static class, but I then don't know how I can use that returned class to access these static methods. I can do it with regular instances of a class, just fine, but doing it with static classes has got me puzzled.
Clarification of Problem:
Some Clarification of The problem I'm trying to solve in case you guys have suggestions of better / more intuitive ways to do this:
Basically I'm interpreting commands from some piece of custom hardware at my company. It's a little data collection gizmo that has a bunch of predefined messages/functions that I have to interpret.
These functions are split into various categories: Display, Keypad, Acquisition, etc.
So basically I have a mapping like this:
Display Category: 128
ShowGraph: 01
ShowText: 02
Keypad Category: 129
F1: 01
F2: 02
MenuKey: 03
I'm making a little stream display that prints the stream of commands out in human readable format. So I'd just print out a big list of something like
Got Category Display, Function ShowGraph
Got Category Keypad, Function MenuKey
Normally I'd use a map for this, but what I want is to also use the functions in each category as constants because I'll have to reference them in if-statements and often times send those same categories back to the little gizmo.
For Instance:
sendMessage(Categories.DisplayCategory.getCategoryInt(), Categories.DisplayCategory.SHOW_GRAPH);
More Code as requested:
public class Functions {
public static interface ICategory{
int getCateogory();
String getCategoryName();
String getFunctionName(int function);
}
private static Map<Integer, Class<? extends ICategory>> catMap = new HashMap<Integer, Class<? extends ICategory>>();
public static String getCategoryString(int category) {
Class<? extends ICategory> clazz = catMap.get(category);
System.out.println(catMap.toString());
if(clazz != null){
try{
Method m = clazz.getMethod("getCategoryName", Integer.class);
return (String) m.invoke(0, category);
}catch (Exception e){
return null;
}
}else{
System.out.println("clazz was null");
return null;
}
}
public static class SystemKey implements ICategory{
public static int CATEGORY = 134;
private static Map<Integer, String> fmap = new HashMap<Integer, String>();
#Override
public int getCateogory() {
return CATEGORY;
}
#Override
public String getCategoryName() {
return "SystemKey";
}
#Override
public String getFunctionName(int function) {
return fmap.get(function);
}
}
public static class SystemCat implements ICategory{
public static int CATEGORY = 128;
private static Map<Integer, String> fmap = new HashMap<Integer, String>();
public static final int POWER_UP = 0x01;
public static final int END_OF_TRANSMIT = 0x02;
public static final int CLEAR_TO_SEND = 0x03;
public static final int NET_TEST = 0x05; /*Fom station to ctrlr*/
public static final int NET_OK = 0x06; /*Response to controller*/
public static final int MAIN_MENU = 0x07;
static{
catMap.put(CATEGORY, SystemCat.class);
fmap.put(POWER_UP, "POWER_UP");
fmap.put(END_OF_TRANSMIT, "END_OF_TRANSMIT");
fmap.put(CLEAR_TO_SEND, "CLEAR_TO_SEND");
fmap.put(NET_TEST, "NET_TEST");
fmap.put(NET_OK, "NET_OK");
fmap.put(MAIN_MENU, "MAIN_MENU");
}
#Override
public int getCateogory() {
return CATEGORY;
}
#Override
public String getCategoryName() {
return "System";
}
#Override
public String getFunctionName(int function) {
return fmap.get(function);
}
}
public static class SoftKey implements ICategory{
public static int CATEGORY = 129;
private static Map<Integer, String> fmap = new HashMap<Integer, String>();
public static final int F1 = 0x20;
public static final int F2 = 0x21;
public static final int F3 = 0x22;
public static final int F4 = 0x23;
public static final int F5 = 0x24;
static{
catMap.put(CATEGORY, SoftKey.class);
fmap.put(F1, "F1");
fmap.put(F2, "F2");
fmap.put(F3, "F3");
fmap.put(F4, "F4");
fmap.put(F5, "F5");
#Override
public int getCateogory() {
return CATEGORY;
}
#Override
public String getCategoryName() {
return "SoftKey";
}
#Override
public String getFunctionName(int function) {
return fmap.get(function);
}
}
public static void main (String[] args) throws Exception{
System.out.println(Functions.getCategoryString(128));
}
}
Update
As I suspected, the solution is quite simple. There are different ways to do this, here is one, I seem to remember calling it Registry, back in the days when Patterns were known as Idioms. You are almost there, what you need is following changes:
Change catMap type from Map<String,Class<? extends ICategory> to Map<Integer, ICategory>.
In the static initializers create an object and put it in the map, e.g.
public static class SoftKey implements ICategory{
....
static{
catMap.put(CATEGORY, new SoftKey());
In getCategoryString use the ICategory object in the registry:
ICategory categ = catMap.get(category);
return categ.getCategoyString()
I might have misunderstood the question, but part of it are confusing:
So catMap.get(catNumber) will actually return the proper static class,
By static class I assume you mean that the interfaces are nested inside some class/interface. There is no such thing as a top-level static class in Java. get returns an Object of a static class, not a class.
but I then don't know how I can use that returned class to access these static methods.
The methods you have declared are not static, they are instance methods
I can do it with regular instances of a class, just fine, but doing it with static classes has got me puzzled.
I am puzzled too. You can call instance methods on objects of static class. Can you post a complete code sample?
Assuming you know all the codes in advance, and there aren't 1000s of function values, this would work. The non-uniqueness of the function value codes isn't a problem as long as you don't mind looking through a container to find them (as opposed to a Map).
You could do away with the static maps completely if you don't mind looping through all the enum values all the time. This could be perfectly acceptable if you don't do lookups very often.
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public enum FunctionCategory {
DISPLAY(128, "Display"),
KEYPAD(129, "KeyPad");
// more categories here...
private final int code;
private final String name;
private static Map<Integer, FunctionCategory> categoryMap = new HashMap<>();
static {
for( FunctionCategory c : FunctionCategory.values() ) {
categoryMap.put(c.getCode(), c);
}
}
// For looking up a category from its code
public static FunctionCategory fromCode( int code ) {
return categoryMap.get(code);
}
private FunctionCategory(int code, String name) {
this.code = code;
this.name = name;
}
public int getCode() {
return code;
}
public String getName() {
return name;
}
public static enum FunctionValue {
// DISPLAY
DISPLAY_GRAPH(DISPLAY, 1, "Graph"),
DISPLAY_TEXT(DISPLAY, 2, "ShowText"),
//KEYPAD
KEYPAD_MENU(KEYPAD, 1, "MenuKey"),
KEYPAD_ENTER(KEYPAD, 2, "EnterKey");
// TODO, others
private static Map<FunctionCategory, Set<FunctionValue>> codeMapping = new EnumMap<>( FunctionCategory.class );
static {
for( FunctionValue fv : FunctionValue.values() ) {
Set<FunctionValue> values = codeMapping.get(fv.getCategory());
if( values == null ) {
values = EnumSet.of(fv);
}
else {
values.add(fv);
}
codeMapping.put(fv.getCategory(), values);
}
}
// First we look up the category, then we just loop over all the values
// within that category. Unless you have lots of values, or really need
// to optimize the lookups, there is no need to do something more complex
public static FunctionValue getFromCodes( int categoryCode, int valueCode ) {
FunctionCategory c = FunctionCategory.fromCode(categoryCode);
if( c != null ) {
Set<FunctionValue> valueSet = codeMapping.get(c);
if( valueSet != null ) {
// Just spin through them, there aren't that many
for( FunctionValue v : valueSet ) {
if( v.getCode() == valueCode ) {
return v;
}
}
}
}
return null;
}
private final FunctionCategory category;
private final int code;
private final String name;
private FunctionValue(FunctionCategory category, int code, String name) {
this.category = category;
this.code = code;
this.name = name;
}
public FunctionCategory getCategory() {
return category;
}
public int getCode() {
return code;
}
public String getName() {
return name;
}
}
}