Object not being replaced - java

I have two lists of contacts, and I want to replace one with another as:
private PhoneCAdapter getContactAdapter(ArrayList<UserAgenda> phoneContacts) throws NetworkConnetionException {
List<UserAgenda> serverContacts = WithingsAPI.getInstance().getContactListByType(Common.CONTACT_LIST_TYPE_FILE,"ALL");
for(UserAgenda pc: phoneContacts){
for(UserAgenda sc : serverContacts){
if(pc.getEmails() != null){
ArrayList<String> emailsPc = new ArrayList<String>(pc.getEmails());
for(String epc: emailsPc){
ArrayList<String> emailList = new ArrayList<String>(sc.getEmails());
String emailServer = emailList.get(0);//server contact has only one email
if(epc.equals(emailServer)){//we have to substitute the object from the server with the phone ones.
pc = sc;
}
}
}
}
}
PhoneCAdapter ca = new PhoneCAdapter(this, 0, phoneContacts,PhoneContacts.this );
return ca;
}
But after the loops my variable phoneContacts still has the same values. Only if I change the fields manually as:
if(epc.equals(emailServer)){
pc.setUserOfWW(sc.getUserOfWW());
if(sc.getInvited().equals("true")){
pc.setInvited("true");
}
else{
pc.setInvited("false");//here we have people who are/arent user of WW
pc.setId2invite(sc.getId2invite());
}
}
How could I replace my object with info from the phone with the user I get from the server, without doing it manually for each field?

Changing the local variable you're using for the iterator doesn't change the content of the collection. It's very important that you understand the difference between modifying the object that a variable's value refers to, and modifying a variable. If you modify the object that the reference within a list refers to, that change will be visible via the list. If you modify a variable which basically contains a copy of that reference, that won't affect the list at all.
I suspect you want:
for (int i = 0; i < phoneContacts.size(); i++) {
UserAgenda pc = phoneContacts.get(i);
for (UserAgenda sc : serverContacts) {
if (pc.getEmails() != null) {
ArrayList<String> emailsPc = new ArrayList<String>(pc.getEmails());
for (String epc: emailsPc) {
ArrayList<String> emailList = new ArrayList<String>(sc.getEmails());
String emailServer = emailList.get(0);
if (epc.equals(emailServer)) {
pc = sc;
// Replace the value in the collection too...
phoneContacts.set(i, sc);
// Do you want to break here?
}
}
}
}
}
It's unclear why you're creating the array lists within the loop, by the way... (or why you're recreating the same list of emails on each iteration). Basically the code is very unclear at the moment, and I strongly suspect it could be simplified considerably - but it's hard to do so without knowing what you're trying to achieve.

Related

dumping or printing the name of a variable

This question mentions xpaths but it is really not specific to xpaths and really concerns any Java Strings.
I am using Java 8 and have about 40 Strings (public static final String in the class). An example is below:
private static final String employeeID_x = "//input[#id = 'id']";
private static final String employeeName = "//input[#id = 'EmployeeName']";
and there are some more complicated ones like
private static final String age_x = "//div[#id = 'Employee']/div[2]/span[1]";
etc. There are 40 of these. I want to verify all the xpaths so I made an array like
private static final String[] arr = {employeeID_x, employeeName_x, age_x, .....};
then to verify
for (String xp: arr) {
List<WebElement> eles = driver.findElement(By.xpath(xp));
if (eles.size() == 0) {
System.out.println(xp + " does not exist");
}
}
you get the idea. This works, but the error message is
"//div[#id = 'Employee']/div[2]/span[1] does not exist". I guess this is ok but I would rather have it say "age_x does not exist".
I don't know how to print the variable name. I have tried using Class and getFields() but that does not seem to work.
What I have to do is duplicate the array and put each element in quotes like this:
private static final String[] names= {"employeeID_x", "employeeName_x", "age_x", .....};
and then get the number of entries and use
for (int i = 0; i < arr.length; i++) {
String xp = arr[i];
String name = names[i];
List<WebElement> eles = driver.findElements(By.xpath(xp));
if (eles.size() == 0) {
System.out.println(name + " does not exist");
}
}
but as you can see this can get to be a pain. Is there anyway to get the name from xp? Maybe no, as I am afraid when it creates the array it substitutes the value of each string?
And as you can see, this is not specific to xpaths.
I don't know how to print the variable name.
With your current array, you can't (reasonably*) unless you can infer the variable name from the string. This line:
private static final String[] arr = {employeeID_x, employeeName_x, age_x, .....};
...copies the value of employeeID_x, etc., into the array. There is no ongoing link between that value and the variable it came from, just as in this code:
a = b;
...there is no ongoing link between a and b.
Your parallel arrays solution works but as you've said isn't ideal. Using a Map may be slightly better:
private static final Map<String, String> map = new HashMap<>();
static {
map.put("employeeID_x", employeeID_x);
map.put("employeeName_x", "employeeName_x);
// ...
}
Then loop through the map's entries, which give you both the name and value. This still has some repetition (e.g., in each put call you have to type the variable name twice), but it's much better from a maintenance perspective: Dramatically harder to get the two out of sync.
Another option is to use reflection: Your array would be of the names of the variables, and then you'd get the variable's value by using Class#getDeclaredField to get a Field instance for it, then get the value via Field#get. E.g., your array would be:
private static final String[] arr = new String[] { "employeeID_x", "employeeName" /*, ...*/ };
...then:
for (String name : names) {
Field f = YourClass.class.getDeclaredField(name);
String value = (String)f.get(null);
// ...test `value` here, report `name` if there's a problem
}
* "reasonably" - You could have the error code compare the string to every one of your fields and report the match, e.g.
if (theString.equals(employeeID_x)) {
theVariableName = "employeeID_x";
} else if (theString.equals(employeeName_x)) {
theVariableName = "employeeName_x";
} else if (...) {
// ...
...but...blech. :-) (And it assumes that two of these never have the same value.)

How to pull specific data from an object in an arraylist

Ok, not sure if the title worded that correctly but say I have three objects with two strings of data each(Lets say a stateName and a cityName) stored into an arraylist. Is it possible to enter in a state name in as a string variable(call it searchStateName), then have a method search through the objects in the list and compare searchStateName to the stateName inside each object in the arraylist, and when a match is found have it return the cityName that is inside the same object as the matching stateName?
I am trying to do something similar currently and would like to figure it out myself, but I have been working on this for the past hour and am completely lost. Could anyone point me in the right direction?
This is the approach. Say you have a class called SC and you have two instance variables in it and getters and setters for them. You need to initialize 3 objects of them inside your main:
SC a = new SC("Illinois ","Chicago ");
SC b = new SC("Michigan ","Detroit");
SC c = new SC("New York"," New York");
And then create an ArrayList of object SC and add those 3 objects of SC to that ArrayList.
ArrayList<SC> list = new ArrayList<SC>();
list.add(a);
list.add(b);
list.add(c);
Now call the method that search for a state name and returns the city name if it finds it:
this.searchStateName("Illinois");
The actual implementation of this method with for-each loop:
public String searchStateName(String stateName){
String result = "No city found.";
for (SC sc : list )
if (sc.getStateName().equalsIgnoreCase(stateName)){
result = sc.getCityName();
break;
}
}
return result;
}
If you are not comfortable with for-each loop then you can use the regular for loop below. I commented out on purpose. But it will work correctly and give you the correct city name.
//public String searchStateName(String stateName){
// String result = null;
// for (int i = 0; i < list.size(); i++){
// if (list.get(i).getStateName() .equalsIgnoreCase(stateName)){
// result = list.get(i).getCityName();
// break;
// }
// }
// return result;
//}
And thats it. Let me know if you need help further.

How to store data in an index in an ArrayList into Arrays in Java

I am new to Java and I am trying to do a calculation using values within a txt file. I have read the txt file, which has 3 tabs, each with three values
I have been able to read the file and get the columns as indices but cannot add the separate values into array. So I want three separate arrays
Read file method
public void read()
{
try
{
FileReader read = new FileReader(file);
String line = null;
while((line = FileReader.readLine()) != null)
{
a.add(line);
}
}
catch (FileNotFoundException e) {}
catch(IOException e) {}
}
Processing method
private void processor () {
for (String li : a)
{
String[] data = li.split("\\s");
Index = Double.parseDouble(data[0]);
Customers = Double.parseDouble(data[1]);
rateOfBuy = Double.parseDouble(data[2]);
}
}
I dont think you are thinking about your data structures correctly. If I were you I would think about this a little differently. To me it makes the most sense just to use a simple array. To handle the complexity of the three columns, I would create a new class called CustomerRate or something to that effect. I would then make the data into instance variables belonging to instances of that class. That way you could just have a simple array of CustomerRate objects and then access the data stored by each of those objects. This will probably be a lot simpler to deal with overall too.
I am not sure exactly what you are trying to accomplish but I'll do my best to help
You would create your new class to be something like this:
your new class:
//This is your new class
public class CustomerRate {
private int person;
private double rate;
//constructor
public CustomerRate(int person, double rate) {
this.person = person;
this.rate = rate;
}
//add appropriate getters and setters and whatever else you need
public double getRate() {
return rate;
}
}
Use the data your parse from your file to create new CustomerRate Objects. Create an array of your objects. Note that this is just an example with one entry with random numbers I'm going to use so you will have to get the loop and parse working:
//creating an example customer
CustomerRate customer1 = new CustomerRate(100, 0.5);
//create your collection to store your customer data that you will add/parse
List<CustomerRate> myList = new ArrayList<CustomerRate>();
//adds to list
myList.add(customer1);
//gets element at index and then grabs the rate
double exampleCustomerRate;
exampleCustomerRate = myList.get(0).getRate();
I coded this quickly so I may have made some mistake but I hope that gives you the general idea of what you should do.
You just need another ArrayList to store your rateOfBusiness. Something like this:
String file = "test.txt";
ArrayList<String> a = new ArrayList<String>();
ArrayList<Double> rateOfBusiness = new ArrayList<>(); //Define with your other fields
Then loop through your data and do the math while adding to the array
private void process () {
for (String li : a)
{
String[] data = li.split("\\t");
Index = Double.parseDouble(data[0]);
Customers = Double.parseDouble(data[1]);; //per year
rateOfBuy = Double.parseDouble(data[2]); //per year
rateOfBusiness.add(Customers*rateOfBuy); //Do math and store for that customer
}
}
Edit: Even though this solves your problem, I would look into learning some Object Oriented principles. IsaacShiffman (or Lvl 9 Oddish, or whatever his name is) has a start on how you would solve this going that direction. Makes your code a lot easier to follow and debug.

Variable might not have been initialized when dealing with array

In a method I created I am trying to create is meant to return an array of user inputted strings. The issue that I am having it the compiler is saying that userData may not be initialized at userData[i]=tempData; and at return userData;. I am unsure why this error is occuring, and would like some feedback.
public String[] getStringObj() {
int i = 0;
String tempData;
String[] userData;
Boolean exitLoop = false;
System.out.println("Please list your values below, separating each item using the return key. To exit the input process please type in ! as your item.");
do {
tempData = IO.readString();
if (tempData.equals("!")) {
exitLoop=true;
} else {
userData[i] = tempData;
i++;
}
} while (exitLoop == false);
return userData;
}
In the interests of improving code quality:
You don't need that exitLoop flag; just do
while(true) {
String input = IO.readString();
if(input.equals("!")) {
break;
}
/* rest of code */
}
Since you seem like you want to just add stuff to an array without bounds, use an ArrayList instead of an array (added bonus, this gets rid of i too):
List<String> userData = new ArrayList<String>();
...
userData.add(line);
If you do these two things, your code will be much more concise and easy to follow.
Your userData is not initilaized and you are attempting to use it here userData[i]=tempData; before initialization.
Initialize it as
String[] userData = new String[20];
//20 is the size of array that I specified, you can specify yours
Also in your while condition you can have while(!exitLoop) instead of while(exitLoop==false)
You didn't initialize the String[]. Just do String[] userData = new String[length]. If you are unsure of the length, you may just want to use an ArrayList<String>.

incorrect Vector.size() returned

I'm implementing a Graph which holds "Book" objects as its nodes. The nodes are connected if the books share a keyword. The keywords for each book are held in a Vector within the Book class. To do this, I've created 3 classes.
1) Books 2) Vertex 3) Graph
The Vertex class holds the Book object and also has a Vector containing all the other Vertex objects (other books which share a keyword). In the Driver, I create the book, pass it to a Graph which then inserts it into a Vertex and finally the Vertex into a Vector named "bookGraph".
public final class Graph {
private Vector<Vertex> bookGraph = new Vector<Vertex>();
private int bookCounter = 0;
public Graph() {
}
public void addBook(Book bk) {
Vertex vtx = new Vertex(bk);
bookGraph.add(vtx);
bookCounter++;
System.out.println("Book #1 has " + bookGraph.get(0).getBook().getKeywords().size() + " keywords");
// addAdjVertices();
}
public void showKeywords() {
System.out.println("Book #1 is " + bookGraph.get(0).getBook().getKeywords().size() + " keywords");
}
The information from the books are read from a file in the Driver and inserted into a book object. I'm trying to make sure that this information is read in correctly and properly inserted into the Graph. My problem occurs when trying to get the size of the keyword Vector within the "showKeywords()" method in the Graph class. bookGraph.get(0).getBook().getKeywords().size() returns 0 when the exact same command in the addBook() method returns the correct size. I've implemented accessor methods such as getTitle() or getAuthor() in the Book class and those work correctly within the showKeywords() method. The keyword vector seems to be the only issue within the showKeywords() method. What am I doing wrong here?
Here is my Driver class....
boolean fileopen = false;
String title, author, keys;
long isbn_number;
Vector<String> keywords = new Vector<String>();
String filename = "books.txt";
String[] keywordTokens;
Scanner fin = null;
Scanner input = new Scanner (System.in);
Graph books = new Graph();
try {
fin = new Scanner (new FileReader(filename));
String fline;
fileopen = true;
System.out.println("Reading books.txt...");
while (fin.hasNextLine()) {
fline = fin.nextLine();
title = fline;
fline = fin.nextLine();
author = fline;
fline = fin.nextLine();
isbn_number = Long.parseLong(fline);
fline = fin.nextLine();
keywordTokens = fline.split(",");
for (int x = 0; x < keywordTokens.length; x++) {
keywords.add(keywordTokens[x]);
}
Book tempBook = new Book(title,author,isbn_number,keywords);
books.addBook(tempBook);
keywords.clear();
if (fin.hasNextLine()) fline = fin.nextLine();
}
books.showKeywords();
System.out.println("Ready.");
}
catch (FileNotFoundException e) {
System.out.println("FILE NOT FOUND!");
}
Looks to me like it should work - there's nothing obviously wrong (like accidentally using static variables). Can you provide a short but complete program which demonstrates the problem? The error is likely to be somewhere else - are you calling setKeywords(new Vector<String>()) somewhere, for example?
Any reason for using Vector rather than the more common ArrayList by the way? I would also suggest that setKeywords(String key) should probably be called addKeyword instead...
EDIT: Okay, now that you've posted the code it's obvious: you're only ever creating a single instance of Vector. You're then reusing that instance for every line, and clearing it at the end.
Just declare your keywords variable inside the loop, create a new instance on every iteration, and don't clear it afterwards.
To make your code as readable as possible (and avoid this sort of thing) I would suggest you declare every variable at the point of first use wherever possible, with the narrowest possible scope.
Could you try this snippet and check whether the error is still there:
public void test() {
Vector<String> keywords = new Vector<String>();
keywords.add("keyword");
Book bk = new Book("Author", "Title", 12345, keywords);
Graph bookGraph = new Graph();
bookGraph.addBook(bk);
bookGraph.showKeywords();
}
I think you got lost in your graph of objects :) I suggest to use unit tests to determine how your code should behave and to make sure it actually does behave the way you expect. The tests can build small examples and then check the various getters to see whether they return the correct results.
For what do you need the copy constructor Book(Book)? Perhaps you put copies of the books instead of the books itself into your collection?

Categories

Resources