Using getters and setters with ArrayLists in java - java

I'm trying to read a csv and storing the records in an ArrayList.
Since I know the no. of records in the csv file I'm specifying the size i.e. 600 when creating the object.
I want the program to be able to read files of unknown no. of records.
How do I make it dynamic.
Here's the working code for the file with 600 records.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.io.*;
public class BankRecords extends Client{
//Create objects for processing data
//private static int count;
static BankRecords[] obj=new BankRecords[600];
static List<List<String>> array = new ArrayList<List<String>>();
#Override
void readData() {
// TODO Auto-generated method stub
String line=" ";
//int i=0;
//try with resources statement
try(BufferedReader br = new BufferedReader(new FileReader("bank-Detail.csv"))){
while((line=br.readLine()) != null) //read from file
{
array.add(Arrays.asList(line.split(",")));
//check data
//count++;
//System.out.println(array.get(i++));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
processData();
}
#Override
void processData() {
// TODO Auto-generated method stub
int idx=0;
for(List<String> bankData: array)
{
obj[idx]= new BankRecords();
obj[idx].setId(bankData.get(0));
obj[idx].setAge(Integer.parseInt(bankData.get(1)));
obj[idx].setSex(bankData.get(2));
obj[idx].setRegion(bankData.get(3));
obj[idx].setIncome(Double.parseDouble(bankData.get(4)));
obj[idx].setMarried(bankData.get(5));
obj[idx].setChild(Integer.parseInt(bankData.get(6)));
obj[idx].setCar(bankData.get(7));
obj[idx].setSact(bankData.get(8));
obj[idx].setCact(bankData.get(9));
obj[idx].setMort(bankData.get(10));
obj[idx].setPep(bankData.get(11));
idx++;
//System.out.println(obj[idx].getId());
}
printData();
}
#Override
void printData() {
//Printing First 25 ID, age, sex, region, income and mortgage
System.out.println("ID\t\tAGE\t\tSEX\t\tREGION\t\tINCOME\t\tMORTGAGE\n");
for(int i=0;i<25;i++){
String s=String.format("%s\t\t%s\t\t%s\t\t%-10s\t%8.2f\t%2s", obj[i].getId(),obj[i].getAge(),obj[i].getSex(),obj[i].getRegion(),obj[i].getIncome(),obj[i].getMort());
System.out.println(s);
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
public String isMarried() {
return married;
}
public void setMarried(String married) {
this.married = married;
}
public int getChild() {
return child;
}
public void setChild(int child) {
this.child = child;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public String getSact() {
return sact;
}
public void setSact(String sact) {
this.sact = sact;
}
public String getCact() {
return cact;
}
public void setCact(String cact) {
this.cact = cact;
}
public String getMort() {
return mort;
}
public void setMort(String mort) {
this.mort = mort;
}
public String getPep() {
return pep;
}
public void setPep(String pep) {
this.pep = pep;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
BankRecords bnk= new BankRecords();
bnk.readData();
}
}

ArrayList can the elements dynamically, so it is not required to know the size in advance.
However, for the BankRecords array, do not initialize it with 600 initially. Instead do something like this:
static BankRecords[] obj = null;
static List<List<String>> array = new ArrayList<List<String>>();
void processData() {
// TODO Auto-generated method stub
obj=new BankRecords[array.size()];
// TODO do your work here
}

You do not have to know the number of records beforehand in order to use an ArrayList. You can specify a default size in the constructor, however it is smart enough to expand itself if you add more records than this.

You are almost there, but for some strange reasons you are using Lists in places where you already have an array; yet on the other side, you are using an array where a List would be a much better fit.
You can rework your code as follows:
// TODO Auto-generated method stub
HINT: those TODOs are generated by your IDE. The idea is that you delete them as soon as you have some real content instead. Keeping them means leaving garbage in your source code. Anything that doesn't add real value to your source code: remove it. Always. Immediately!
String line=" ";
List<Bankrecord> records = new ArrayList<>();
//int i=0; ... again: unused code --- remove that!
try(BufferedReader br = new BufferedReader(new FileReader("bank-Detail.csv"))){
while((line=br.readLine()) != null) //read from file
{
String[] lineData = line.split(",");
BankRecord recordForNewLine = buildRecordFrom(lineData);
records.add(recordForNewLine);
} ...
And then you could rework your processData into something like:
private BankRecord buildRecordFrom(String[] lineData) {
BankRecord newRecord = new BankRecords();
newRecord.setId(lineData[0];
...
return newRecord;
}
And things that you should really consider changing, too:
Building your bank records by simply assuming that column contains a valid ID, and the next column contains a valid xyz ... is a bad idea.
Instead, you should be validating all your input: you should check that each array you gain from split has **exactly the expected length. And then have to validate that each value from that array has the expected "content"
Then, from a modelling perspective: you have a ton of setters on your Bankrecord class. But that is simply wrong! In real life, when some "record" is created, then its essential properties (such as its ID) can't be changed after creation!
Instead, you should make sure that such properties in your class can't be changed after the object has been created. The way to go here: Builder pattern!
Finally: my code above is meant as "inspiration point" to get you going. Dont blindly copy/paste it; there might be various typos in - just read it until you get what (and why) it is doing (what it is doing)!
Then: I hope you understand that real CSV parsing is much more complicated than splitting around "," (for example: strings in CSV data can contain ',' too; and then your simple split would rip up that string!)
If you are serious about parsing real-world-other-people CSV input, then you better look into using existing libraries to do this for you. Writing a correct CSV parser is hard work (and not very rewarding; since that means re-inventing a complicated wheel for no good reason)!

Related

Get all variable names in methods

I would like to retrieve all variable names in all methods of a java file. Example Like a Person.java contains
class Person {
private String firstName;
private String lastName;
public static void main() {
String test = "test";
Person p1 = new Person();
p1.setName("John");
}
public void setName(String name) {
this.firstName = name;
}
}
i would like to be able to print out all variables declared. I have tried using javaparser to retrieve them.
However, i can only retrieve variables declared in the class which is
firstName
lastName
I want to be able to retrieve all variables declared in main method as well
firstName
lastName
test
My javaparser method is
public static void getVariables(String inputFilePath) {
try {
CompilationUnit cu = StaticJavaParser.parse(new File(inputFilePath));
cu.findAll(FieldDeclaration.class).forEach(field -> {
field.getVariables().forEach(variable -> {
System.out.println(variable.getName());
variable.getInitializer().ifPresent(initValue ->
System.out.println(initValue.toString()));
});
});
} catch (FileNotFoundException fe) {
System.out.println(fe.getMessage());
} catch (IOException e){
System.out.println(e.getMessage());
}
}
Solved
As following Eugene's suggestion, i am able to retrieve all variables now
public static void getVariables(String inputFilePath) {
try {
CompilationUnit cu = StaticJavaParser.parse(new File(inputFilePath));
cu.findAll(VariableDeclarator.class).forEach(variable -> {
System.out.println(variable);
});
} catch (FileNotFoundException fe) {
} catch (IOException e) {
}
}
You are passing FieldDeclaration.class into CompilationUnit's findAll() method. So, as asked, it gets you all declared fields.
If you want to list all declared variables, use VariableDeclarator.class from the same package – it will get you all of those, including the ones declared as fields.

Constructors and methods in java

I want to create the below class
associatename:String
workstatus:String
associate() :constructor
getassociatename():String
setassociatename(String):void
getworkstatus()String
tracksassociatestatus():int
setworkstatus(String):void
The trackAssociateStatus method takes the number of days as argument and sets the work status of the associate based on the number of days. The first 20 days they learn “C”, the next 20 days they learn “Java” In the Main class invoke the trackAssociateStatus method and find the work status and display the output.
output:The associate abc work status:Project phase
I tried this....But i got error
//associate class
public class associate{
private int associatename;
private String workstatus;
private int days;
void associate()
{
getassociatename();
setassociatename();
getworkstatus();
tracksassociatestatus();
setworkstatus();
}
public int getassociatename()
{
return associatename;
}
public void setassociatename(int associatename)
{
this.associatename=associatename;
}
public String getworkstatus()
{
return workstatus;
}
public void tracksassociatestatus(int days)
{
if(days<20)
setworkstatus("C");
else
setworkstatus("Java");
}
public void setworkstatus(String workstatus)
{
this.workstatus=workstatus;
}
}
//main class
associate a =new associate();
Scanner in=new Scanner(System.in);
int associateid=0;
String workstatus=null;
int days=0;
System.out.println("Enter the associateid:");
associateid=in.nextInt();
a.associateid=(associateid);
System.out.println("Enter the no of days:");
days=in.nextInt();
a.trackassociatestatus();
System.out.println("The id is "+a.getassocaiteid()+" work status "+a.getworkstatus());
Based on your (seemingly) UML spec, your class would look like the following:
public class Associate {
private String associateName;
private String workStatus;
public Associate() {
// This constructor is optional, a no-args constructor is added by the compiler to any class not explicitly naming a constructor.
}
public String getAssociateName() {
return associateName;
}
public void setAssociateName(String associateName) {
this.associateName = associateName;
}
public String getWorkStatus() {
return workStatus;
}
public void setWorkStatus(String workStatus) {
this.workStatus = workStatus;
}
public int tracksAssociateStatus() {
// TODO write logic here
return 1; // TODO change to whatever you need to return
}
}
You were specifying int for getAssociateName, when associateName is a String. This won't work; you need your getter return type to be the same as your field data type, or you need to convert the data to the method's return type. (The former is best practice).
Constructors don't specify a type, the class name is used and the compiler will understand what you want to do (which is return a new instance of the class). Therefore, your void associate() will tell the compiler "create a method called associate that doesn't return anything".
Well, would be nice if you provide the error itself for us.
But meanwhile, have you notice that your tracksassociatestatus method recieves an integer parameter days, and your constructor passes nothing to it?
So try changing your constructor to be something like:
Public associate() {
getassociatename();
setassociatename();
getworkstatus();
tracksassociatestatus(10);
setworkstatus();
}
For a cleaner code, check the other answer.
If you still have errors, please share them.
import java.util.*;
public class Associate
{
private String associateName;
private int workStatus;
private int days;
Scanner sc = new Scanner(System.in);
public String getAssociateName()
{
System.out.println("Enter the Associate id:");
associateName = sc.nextLine();
return associateName;
}
public void setassociatename(int associatename)
{
this.associateName=associateName;
}
public String tracksAssociatename()
{
return associateName;
}
public int getWorkStatus()
{
System.out.println("Enter the number of days");
days = sc.nextInt();
return days;
}
public void setWorkStatus(String workStatus)
{
this.workStatus=workStatus;
}
enter code here
public `enter code here`int tracksAssociateStatus()
{
return days;
}
public static void main(String args[])
{
Associate obj = new Associate();
obj.getAssociateName();
obj.getworkstatus();
System.out.println("The Associate name "+obj.tracksAssociatename()+" work Status "+obj.tracksAssociateStatus());
}
}

Check if class has a variable in its constructor based on a string?

Let's say I have a class named Person and its constructor had variables like name, age, hairColor and so on. If I had a function that receives a string that should match one of the class's variables, how could I check if that class actually had that variable and how could I go about modifying it? For example:
public class Person {
public String name;
public int age;
public String hairColor;
public Person() {
name = "Bryce";
age = 21;
hairColor = "brown";
}
public void changeHairColor(String variable, String color) {
if (/*this class contains the variable passed as an argument to this method*/) {
// Person[variable] = color
}
}
}
I'm a python dev, mostly, so the method changeHairColor has some pseudo-python in it. I want to be able to edit the variable in a similar way you could edit variables inside of dictionaries with Python:
person = {
"name": "Bryce",
"age": 21,
"hairColor": "brown"
}
def changeHairColor(variable, color):
person[variable] = color
If that is at all possible.
The only way to do it in Java is to use Java Reflection API:
public class Test {
public String name;
public int age;
public String hairColor;
public void setProperty(String property, Object value) {
try {
Field declaredField = this.getClass().getDeclaredField(property);
switch (declaredField.getAnnotatedType().getType().getTypeName()) {
case "java.lang.String":
declaredField.set(this, value);
break;
// handle other types
}
} catch (NoSuchFieldException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}
}
public static void main(String[] args) {
Test test = new Test();
test.setProperty("name", "Bob");
System.out.println(test.name);
}
}
I would not solve this with reflection. If your PlayerCharacter has an enumerable set of attributes, I would model these as a Java enum and store the attribute values within the PlayerCharacter object in an EnumMap:
import java.util.EnumMap;
public class PlayerCharacter {
public enum Attribute {
AGILITY,
DEXTERITY,
/* etc ...*/
VITALITY
}
private EnumMap<Attribute, Integer> attributes = new EnumMap<>(Attribute.class);
public PlayerCharacter() {
// initialize each attribute with a default value (0 in this example)
for (Attribute a : Attribute.values()) {
attributes.put(a, new Integer(0));
}
}
public int getValue(Attribute attribute) {
return attributes.get(attribute);
}
public void levelUp(Attribute attribute, int amount) {
attributes.put(attribute, attributes.get(attribute) + amount);
}
}
The biggest benefit of using an enum instead of plain old String (+reflection), is that this way you get compile-time type safety for the code that's using your PlayerCharacter.
Using Reflection API, you can access the methods and properties on an object at run time. The other answer describes its usage. But I don't recommend reflections for your problem. How about the following:
public void changeHairColor(String variable, String color) {
if("name".equalsIgnoreCase(variable))
this.name = color;
else if("age".equalsIgnoreCase(variable))
this.age = Integer.parseInt(color);
else if("color".equalsIgnoreCase(variable))
this.color = color;
else
throw new Exception ("error - property not available");
}
}
Note, your existing method name 'changeHairColor' doesn't make sense in the context. It should be someething like 'changeProperty' because you are not just changing the 'color', you are changing any available property with this method.

Array Of Methods That Return A String

I'm creating a kind of data testing program, and one specific part is giving me a huge amount of trouble. In my main method class there is one section where I need to send over a String of data as a parameter in a method to my methods class (let's call it ValidatorClass) and the idea being that the method will then return any validation errors or if there are none simply an empty String.
This would be fine except that I use "for loops" when going through my data to validate as doing it without is just too clunky. I tried to research about arrays of methods and found plenty of useful things that work with void methods but found nothing on any methods that return variables.
In a nutshell I'm asking: Is it possible to create an array of methods (or implement an array of objects to simulate an array of methods) that return a variable?
Here is some example code, but in the actual program the method's return would actually be used further on:
public class Validation{
public static void main(String args){
ValidatorClass valTest = new ValidatorClass();
String[] dataList = {"Andrew", "Jameson", "Male"}
for(int i = 0; i < dataList.length; i++){
String errors = valTest.testInput(dataList[i], i).validationList[i];
System.out.println(errors);
}
}
}
And in ValidatorClass:
public class ValidatorClass{
public String testInput(String data, int index){
//Tests the data by calling method "index" which corresponds to data type.
//ie. validateName would be index : 1, validateSurname index : 2 etc
String errors = validationMethodList[index](data); //Somehow add data as a parameter to it
return errors;
}
public String validateName(String name){
String errors = "";
if(name.length < 1){
errors += "Name Not Entered";
}
return errors;
}
public String validateSurname(String surname){
String errors = "";
if(surname.length < 1){
errors += "Surame Not Entered";
}
return errors;
}
public String validateGender(String gender){
String errors = "";
if(!gender.equalsIgnoreCase("male") || !gender.equalsIngoreCase("female")){
errors += "Invalid Gender";
}
return errors;
}
}
I imagine that you have something like...
static String validate1(Validatible v) { /* do something */ }
static String validate2(Validatible v) { /* do something else */ }
static String validate3(Validatible v) { /* do something still else */ }
And that you want to execute, in some method...
Validatible v = getValidatible();
System.out.println(validate1(v));
System.out.println(validate2(v));
System.out.println(validate3(v));
Then perhaps you could write an interface:
public interface Validator {
String validate(Validatible v);
}
...and keep them in an array or a list...
private static final List<Validator> validators = Arrays.asList(
new Validator() {
#Override
public String validate() {
/* do something */
}
},
new Validator() {
#Override
public String validate() {
/* do something else */
}
},
new Validator() {
#Override
public String validate() {
/* do something still else */
}
}
);
// Can be written more compactly if in Java 8.
Thereafter, you can call the methods in a for-loop:
Validatible v = getValidatible();
for(Validator validator : validators) {
System.out.println(validator.validate(v));
}
Possible improvements would include using a StringBuilder to build a single String (or using the Stream API and using Collectors.joining) if this fits your purpose better.

Java Object Array Foreach Method Access

After developing in PHP for a long time I have decided to step into Java. Comfortable in OOP methodology and all that, I'm trying to start off at that point within java, but I'm getting hung up on passing out my arraylist object into a for statement to be printed back out using the Item class methods.
HelloInvetory.java
package helloInventory;
import java.util.Arrays;
public class HelloInventory {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Object InvetoryItems;
Inventory inv = new Inventory();
inv.createItemObj(101, "camera", "Used camera that I bought off of a homeless guy.", 500);
InvetoryItems = inv.getAllInventoryItems();
for(Object item : InvetoryItems){
System.out.println(item.getItemName());
}
System.out.println("Done");
}
}
Inventory.java
package helloInventory;
import java.util.*;
/**
* Tracks and maintains all items within the inventory
* #author levi
*
*/
public class Inventory {
List<Object> InventoryItems = new ArrayList<Object>();
/*
* create object from Items class
* and insert into Object[] array.
*/
public void createItemObj(int sku, String name, String descriptor, float price) {
Items item = new Items();
item.setSku(sku);
item.setItemName(name);
item.setItemDescription(descriptor);
item.setItemPrice(price);
this.setInventoryItems(item);
}
public Object getAllInventoryItems() {
//return InventoryItems;
return this.InventoryItems.toArray();
}
public void setInventoryItems(Object inventoryItems) {
//InventoryItems.add(inventoryItems);
this.InventoryItems.add(inventoryItems);
}
}
Items.java
package helloInventory;
/**
* Class object to hold each item details
* #author levi
*
*/
public class Items {
int sku;
String itemName;
String itemDescription;
float itemPrice;
public int getSku() {
return sku;
}
public void setSku(int sku) {
this.sku = sku;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getItemDescription() {
return itemDescription;
}
public void setItemDescription(String itemDescription) {
this.itemDescription = itemDescription;
}
public float getItemPrice() {
return itemPrice;
}
public void setItemPrice(float itemPrice) {
this.itemPrice = itemPrice;
}
}
Where I am stuck is within the HelloInventory.java
for(Object item : InvetoryItems){
System.out.println(item.getItemName());
}
IDE (Eclipse) gives me the error "Can only iterate over an array or an instance of java.lang.Iterable". Is there something extra I need, or I'm I going around this totally the wrong way in Java? Correct example would be helpful.
Best,
Levi
You have a very strange architecture here my friend. You shouldn't be using generic Objects everywhere, but the actual types. First thing:
public Object getAllInventoryItems() {
//return InventoryItems;
return this.InventoryItems.toArray();
}
Why not just return the List itself?
public List<Item> getAllInventoryItems() {
return this.InventoryItems;
}
Also change this:
List<Item> InventoryItems = new ArrayList<Item>();
and this:
public void setInventoryItems(Item inventoryItems) {
this.InventoryItems.add(inventoryItems);
}
Now iterating the List is smooth sailing:
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Item> InvetoryItems;
Inventory inv = new Inventory();
inv.createItemObj(101, "camera", "Used camera that I bought off of a homeless guy.", 500);
InvetoryItems = inv.getAllInventoryItems();
for(Item item : InvetoryItems){
System.out.println(item.getItemName());
}
System.out.println("Done");
}
Btw, I changed Items to Item out of habit. A class name should indicate a single entity so by convention it's singular.
Now don't take this the wrong way, but you may have got off on the wrong foot with Java, so I highly recommend this reading: http://www.mindview.net/Books/TIJ/ This worked for me when I was starting with Java, maybe others can suggest some good sources as well.
Ok, two things. One is that Tudor is absolutely right, it's best to use the classes you're expecting directly, not Objects, and stylistically his points are accurate too.
Two is that if you really have to use a list of object, you'll need to cast back from object to whatever type it is that you're expecting to receive.
List<Object> list = inv.getAllInventoryItems();
for (Object item : list){
System.out.println((Items) item).getItemName();
}
However, I wouldn't recommend doing this as it effectively takes what should be a compile-time error and makes it a RunTime error (if the class cannot be cast).

Categories