Is there a way to use getter method as a variable, I mean in here i want to replace getDiscountCode() with a variable
for (int row=0; row < pOSBean.getItemList().size(); row++) {
valueDTO = new ValueDTO();
valueDTO.setRowId(1);
valueDTO.setValue(pOSBean.getItemList().get(row).getDiscountCode());
valueListDTO.add(valueDTO);
}
something like this
variable = getDiscountCode();
for (int row=0; row < pOSBean.getItemList().size(); row++) {
valueDTO = new ValueDTO();
valueDTO.setRowId(1);
valueDTO.setValue(pOSBean.getItemList().get(row).+variable);
valueListDTO.add(valueDTO);
}
i can't use 'pOSBean.getItemList().get(row).getDiscountCode()' row as a variable cuz rowid is there
any Suggestions plz
public List<ItemCartDTO> getItemList() {
return itemList;
}
public class ItemCartDTO implements Serializable {
private String locCode;
private List<CommonDropdownItemsDTO> selectedItmStockList;
private String discountCode;
public String getDiscountCode() {
return discountCode;
}
public void setDiscountCode(String discountCode) {
this.discountCode = discountCode;
}
...
}
You can use the functional interface Function for that purpose:
Function<Integer, DISCOUNT_CODE> method = (row) -> pOSBean.getItemList().get(row).getDiscountCode(); // Edit DISCOUNT_CODE Type
The Function will take a Integer (your row) and return the discount code:
valueDTO.setValue(method.apply(row));
You may also look into the enhanced for loop. With that type of loop you can make your loop even prettier:
for (Item item : pOSBean.getItemList())
{
valueDTO = new ValueDTO();
valueDTO.setRowId(1);
valueDTO.setValue(item.getDiscountCode());
valueListDTO.add(valueDTO);
}
There are some important details missing. For example, when you call valueDTO.setValue(...), what type does setValue expect? Any Object? A String? Some custom class? If it's a custom class, are there really multiple getters that you could vary between, that would return that class?
Say setValue's parameter is an Object. If getRow() returns something of class YourClass, you can write:
Function<YourClass, Object> getter = YourClass::getDiscountCode;
and call it like this:
valueDTO.setValue(getter.apply(pOSBean.getItemList().get(row)));
Related
I have a object and i get some fields from it, i made a method with a switch statement, the idea was make it generic and just call this method through parameters but now I´m not sure.
The options are
private String getCode(Row row, String code) {
String result;
switch (code) {
case code1:
result = row.getString("constant1");
break;
case code2:
result = row.getString(constant2);
break;
case code3:
result = row.getString(constant3);
break;
case code4:
result = row.getString(constant4);
break;
default:
result = null;
}
return result;
}
or
private String getcode1(Row row){
return row.getString("constant1")
}
private String getcode1(Row row){
return row.getString("constant2")
}
private String getcode1(Row row){
return row.getString("constant3")
}
private String getcode1(Row row){
return row.getString("constant4")
}
I wand to use the better way, I´m a little confuse
The answer is neither of the them.
What you have here is a value conversion process. How this works? Well, as far I understand, you need to store the data in form of key-value pair where key must be unique. So this is the definition of a HashMap in java.
Also, because you are using Switch I'm assuming that you can identify your data with some unique key. This meas for each code there is only one constant. But how we can apply this to my issue? Well, I think you have a collection of data from where you extracted a single row. Now, from this row you want to access to a value (lets call it codeValue) using a constant, but to get this constant you need a code. Like this: code->constant->codeValue
How can I implement this??
Well, we gonna need a HasMap() called constants, which defines its keys a codes and the values as constants. Now you easily get each constant if you know its code. Obviously, if you get the constant you can also get the codeValue of each `row, like this:
public class TestClass {
public static void main(String[] args) {
// Create a HashMap object called constants
Map<String, String> constants = new HashMap<String, String>();
// Add keys and values (code, constant)
constants.put("code1", "constant1");
constants.put("code2", "constant2");
constants.put("code3", "constant3");
constants.put("code4", "constant4");
System.out.println(constants);
Row row = loadRow();
String code = loadCode();
//How to use it
String result = getCodeValue(row, code);
System.out.println(result);
}
// Now you get the code from the Map
private String getCodeValue(Row row, String code) {
return row.getString(constants.get(code));
}
}
In case your input code is different than constant, I will suggest the following approach. Create an Enum mapping code and constant.
public enum Mapping {
MAPPING_FIRST("code1", "constant1"),
MAPPING_SECOND("code2", "constant2");
private String code;
private String constant;
// constructor and getters
public static Mapping getMappingFromCode(String code){
return Arrays.stream(Mapping.values())
.filter(mapping -> mapping.getCode().equals(code))
.findFirst()
.orElse(null);
}
}
Now, create a method to access value from row.
private String getValue(Row row, String code) {
Mapping mapping = Mapping.getMappingFromCode(code);
if(mapping == null){
return null;
}
return row.getString(mapping.getConstant());
}
This question is little bit to much, but I will try to explain best I could. For me second option is no no at all. Why? You are making methods that you will have to sort out with some if/else statements anyway, for example:
if (code.equals(code1))
someString = getcode1(row);
else if (code.equals(code2))
somestring = getcode2(row);
else if (code.equals(code3))
someString = getcode3(row);
else
someString = getcode4(row);
Why not use this:
if (code.equals(code1))
someString = row.getString("content1");
else if (code.equals(code2))
somestring = row.getString("content2");
else if (code.equals(code3))
someString = row.getString("content3");
else
someString = row.getString("content4");
The first one I can see being used, but there is alternative there. Give us entire minimal requirement code with entire class and methods and we could help you far more than using these snippets of code.
Create an enum for mapping of code and constant. In that enum, create a generic method where you can get code just passing through parameter.
public enum MyEnum {
CODE1("constant1"), CODE2("constant2");
private String constant;
public String getConstant() {
return constant;
}
private MyEnum(String constant) {
this.constant = constant;
}
private static String getConstant(String code) {
return Arrays.stream(MyEnum.values()).filter(mapping -> mapping.name().equalsIgnoreCase(code))
.map(e -> e.getConstant()).findAny().orElse(null);
}
public static String getCode(Row row, String code) {
String constant = getConstant(code);
return constant != null ? row.get(constant) : null;
}
}
You can get code from row object by calling genric method getCode().
MyEnum.getCode(row, "code1")
I'm sitting on an assignment for university and I'm at a point, where I fear I haven't really understood something fundamental in the concecpt of Java or OOP altogether. I'll try to make it as short as possible (maybe it's sufficient to just look at the 3rd code segment, but I just wanted to make sure, I included enough detail). I am to write a little employee management. One class within this project is the employeeManagement itself and this class should possess a method for sorting employees by first letter via bubblesort.
I have written 3 classes for this: The first one is "Employee", which contains a name and an ID (a running number) , getter and setter methods and one method for checking whether the first letter of one employee is smaller (lower in the alphabet) than the other. It looks like this:
static boolean isSmaller(Employee source, Employee target) {
char[] sourceArray = new char[source.name.length()];
char[] targetArray = new char[target.name.length()];
sourceArray = source.name.toCharArray();
targetArray = target.name.toCharArray();
if(sourceArray[0] < targetArray[0])
return true;
else
return false;
}
I tested it and it seems to work for my case. Now there's another class called EmployeeList and it manages the employees via an array of employees ("Employee" objects). The size of this array is determined via constructor. My code looks like this:
public class EmployeeList {
/*attributes*/
private int size;
private Employee[] employeeArray;
/* constructor */
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
}
/* methods */
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
/* adds employee to end of the list. Returns false, if list is too small */
boolean add(Employee m) {
int id = m.getID();
if (id > employeeArray.length) {
return false;
} else {
employeeArray[id] = m;
return true;
}
}
/* returns employee at certain position */
Employee get(int index) {
return employeeArray[index];
}
/* Sets employee at certain position. Returns null, if position doesn't exist. Else returns old value. */
Employee set(int index, Employee m) {
if (employeeArray[index] == null) {
return null;
} else {
Employee before = employeeArray[index];
employeeArray[index] = m;
return before;
}
}
Now comes my real problem: In a third class called "employeeManagement" I am supposed to implement the sorting algorithm. The class looks like this:
public class EmployeeManagement {
private EmployeeList ml = new EmployeeList(3);
public boolean addEmployee(Employee e) {
return ml.add(e);
}
public void sortEmployee() {
System.out.println(ml.getSize()); // I wrote this for debugging, exactly here lies my problem
for (int n = ml.getSize(); n > 1; n--) {
for (int i = 0; i < n - 1; i++) {
if (Employee.isSmaller(ml.get(i), ml.get(i + 1)) == false) {
Employee old = ml.set(i, ml.get(i + 1));
ml.set(i+1, old);
}
}
}
}
The "println" before my comment returns "0" in console... I am expecting "3" as this is the size I gave the "EmployeeList" as parameter of the constructor within my "EmployeeManagement" class. Where is my mistake ? And how can I access the size of the object I created in the "EmployeeManagement" class (the "3") ? I'm really looking forward to your answers!
Thanks,
Phreneticus
You are not storing size in your constructor. Something like,
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
this.size = size; // <-- add this.
}
Also, setSize isn't going to automatically copy (and grow) the array. You will need to copy the array, because Java arrays have a fixed length. Finally, you don't really need size here since employeeArray has a length.
The size variable you are calling is the class field. If you take a quick look at your code, the getter is getting the field (which is initialized as zero when created). The size you are using it. The good way of doing it would be to get the size of the array in the getter like this:
public int getSize() {
return employeeArray.length;
}
This would return the size of the array in the object.
I have this class that serves as a container which I will use the instance variable for processing later
class Data{
static int counter= 0;
boolean boolean1;
String string1;
public Data() {
counter++;
}
}
And I have this method that sets the values of Data
public Data setData()
{
Data data = null;
for (int i = 0; i < somecoutnerhere; i++) {
Data = new Data();
Data.boolean1 = some boolean put here;
Data.string1 = "some string to be put here";
}
return ProcessData(Data);
}
I also have this class ProcessData that will make use of Data and will construct the response
private class ProcessData
{
private final Map<String, List<?>> map = new HashMap<String, List<?>>();
int counter;
public ProcessData(Data data)
{
map.put("boolean1", data.boolean1);
map.put("String1", data.string1);
counter = data.counter;
}
public String someMethodToGenerateReturnData(){
// some code here to make use of the Data collected. Will basically use map to construct the return String
}
}
My problem is that I couldn't figure out how can I return all the instance variables created on the for-loop for Data on setData(). Any thoughts?
My problem is that I couldn't figure out how can I return all the instance variables created on the for-loop for Data on setData(). Any thoughts?
According to this your problem is not "returning all instance one variables in one call", as your title states, but rather a question about how returning all Data-Objects created in your for-loop, which is easier.
Your code is erronous though, so I went ahead & corrected it (I hope I didn't mess up). I also renamed a few things.
The changes I made are:
renamed "boolean1" and "string1" to "trueOrFalse" and "string"
added a public, fully parameterized constructor to the Data-class
added a ProcessData-list to the setData()-method, which is filled in the for-loop
(+ a comment)
However, I'd strongly recommend you to check your architecture, and also to learn a bit about naming conventions, or coding conventions in general. Names should point out the purpose or content of the method/variable/class, and "boolean1" isn't really doing that.
Regarding the architecture: The Data-class seems to exist solely for the counter, and you could easily change that, making the Data-class obsolete (unless it's used somewhere else).
Data class:
class Data {
static int counter = 0;
boolean trueOrFalse;
String string;
public Data() {
counter++;
}
public Data(boolean someBoolean, String someString) {
this.trueOrFalse= someBoolean;
this.string = someString;
counter++;
}
}
setData()-Method:
public List<ProcessData> setData() {
List<ProcessData> processedDataList = new ArrayList<ProcessData>();
for (int i = 0; i < someCounterHere; i++) {
processedDataList.add(new ProcessData(new Data(true, "testString"));
// a new Data-object is created (parameters true and "testString")
// a new ProcessData-object is created (parameter is the newly created Data-Object)
// the newly created ProcessData-object is added to the list
}
return processedDataList;
}
ProcessData-class:
private class ProcessData {
private final Map<String, List<?>> map = new HashMap<String, List<?>>();
int counter;
public ProcessData(Data data) {
map.put("trueOrFalse", data.trueOrFalse);
map.put("string", data.string);
counter = data.counter;
}
public String someMethodToGenerateReturnData() {
// some code here to make use of the Data collected. Will basically use map to construct the return String
}
}
I have a class called Bean which has 3 fields
public class Bean {
private Object field0;
private Object field1;
private Object field2;
public Object getField0() {
return field0;
}
public void setField0(Object field0) {
this.field0 = field0;
}
public Object getField1() {
return field1;
}
public void setField1(Object field1) {
this.field1 = field1;
}
public Object getField2() {
return field2;
}
public void setField2(Object field2) {
this.field2 = field2;
}
I want to set each one of the fields with data to do so
int j, i;
for (j = 0; j < body.size(); j++) {
line = new Bean();
List row = body.get(j);
HashMap map = new HashMap(headers.length);
for (i = 0; i < headers.length; i++) {
line.choosefield2(i, headers, row);
}
list.add(line);
}
and choosefield2 is in the bean:
public void choosefield2(int i, String[] headers, List row) {
switch (i) {
case 0:
this.setField0(row.get(0));
break;
case 1:
this.setField1(row.get(1));
break;
case 2:
this.setField2(row.get(2));
break;
Can I do this in a for cycle instead of doing a case switch? I have way more than 3 fields so it's not really practical. I heard reflections might be an option. I wanted something like
for (i = 0; i < headers.length; i++) {
line.setField[i]=row.get(i);
}
list.add(line);
}
is this possible? Using JDK 1.6
You can, the question is, if you should. Of course you can dynamically search the methods and invoke them via reflection.
Class<?> clz = Bean.class;
Method[] methods = clz.getDeclaredMethods();
// etc.
methods[i].invoke( ... );
But this does NOT help you make your code more readable typically - and it will slow down your application. Also you of course lose much type-safety and compiler checking, potentially replacing many compiler errors with exceptions occuring during runtime. You should only do so if you have not other choices.
This sounds like an ideal task for Java 8:
// keep and reuse this list:
List<BiConsumer<Bean,Object>> setters=Arrays.asList(
Bean::setField0, Bean::setField1, Bean::setField2);
Bean bean;
List<Object> values;
assert setters.size()==values.size();
for(int i=0, num=setters.size(); i<num; i++)
setters.get(i).accept(bean, values.get(i));
This code does not use Reflection but rather an explicit list of defined properties, so you’ll notice errors at compile time already. But adding a new property is still as easy as adding Bean::setNewProperty to the list at the beginning…
The construction of all beans may look like:
List<List<?>> body;
List<Bean> beans=body.stream().map(row-> {
Bean bean=new Bean();
for(int i=0, num=setters.size(); i<num; i++)
setters.get(i).accept(bean, row.get(i));
return bean;
}).collect(Collectors.toList());
Apache commons-beanutils is a project that was created to make dealing with beans easier than using raw reflection. You could do something like this:
Map<String, String> properties = BeanUtils.describe(bean);
List<String> orderedProperties = new ArrayList<>(properties.keySet()); // cache in an instance variable
// sometime later...
BeanUtils.setProperty(obj, orderedProperties.get(i), value);
Just be careful about BeanUtils because I seem to remember it thinking getClass() was a property because it looks like a getter. You might want to check for a setter on each property that BeanUtils finds.
Please see section "Programmatically Specifying the Schema". Java section.
The example works. But I have a question about this particular code snippet.
JavaRDD<Row> rowRDD = people.map(
new Function<String, Row>() {
public Row call(String record) throws Exception {
String[] fields = record.split(",");
return Row.create(fields[0], fields[1].trim());
}
The Row create method is being called with a static number of objects determined at compile time.
However, in my code, I need to call the Row.create method for a dynamic number of arguments.
I will only know the number of fields at run time
For example, it may be one of:
return Row.create(fields[0], fields[1].trim(), fields[2]);
or
return Row.create(fields[0]);
or
return Row.create(fields[0],fields[1].trim(), fields[2], fields[3],fields[4]);
How do I do it?
Here is how you can do it. Worked for me.
JavaRDD<Row> rowRDD = people.map(
new Function<String, Row>() {
public Row call(String record) throws Exception {
String[] fields = record.split(",");
//return Row.create(fields[0], fields[1].trim());
Object[] fields_converted = fields;
return Row.create(fields_converted);
}
});
Try using elipsis in your implemented method as below.
public static void create(String ...arg) { ... }
Elipsis accept n number of arguments.
You can specify a method to take multiple arguments by using three dots after the argument, for example:
public static <return_type> create(String...args){
// Yoo can now use the String[] args
}
Replace with your desired return type.
Please change the signature of your call method as you have not specified a return type for it!
Here is what I did in the same situation
new Function<String, Row>(String s) {
public Row call(String s){
int n = /* width of actual schema */
Object rec[] = new Object[n];
for( int i = 0; i < n; ++i )
rec[i] = /* Something that aligns with the type of #i field */
return Row.create( rec );
}
}
There might be dragons here. My version compiles, looks good, not tested yet.