ArrayList displaying only the last value of index - java

public ArrayList getEmpInfo(int id) {
ArrayList data = new ArrayList();
loginPojo lp=new loginPojo();
EmployeeInfoPojo emp_info = new EmployeeInfoPojo();
Session session = null;
SessionFactory sessionfactory = new Configuration().configure().buildSessionFactory();
session = sessionfactory.openSession();
String sql_query = "from loginPojo where id!=" + id;
Query query = session.createQuery(sql_query);
List<loginPojo> list = query.list();
Iterator it = list.iterator();
while (it.hasNext()) {
lp = (loginPojo) it.next();
emp_info.setName(lp.getName());
System.out.println("Before "+emp_info.getName());
data.add(emp_info);
System.out.println("After "+emp_info.getName());
}
return data;
}
This is the code for getting the information from the database using the hibernate framework.I tried to display the ArrayList in the main using the following code.
public static void main(String args[]) {
EmployeeInfoPojo emip = null;
EmployeeInfo emi = new EmployeeInfo();
ArrayList info = emi.getEmpInfo(102);
Iterator it = info.iterator();
while (it.hasNext()) {
emip = (EmployeeInfoPojo) it.next();
System.out.println(emip.getName());
}
}
The output Expected is:
John
Jose
Mark
But what am getting is:
Mark
Mark
Mark
Can anyone find me what's wrong with the code????

I think you need to change the below logic...
while (it.hasNext()) {
lp = (loginPojo) it.next();
emp_info.setName(lp.getName());
System.out.println("Before "+emp_info.getName());
data.add(emp_info);
System.out.println("After "+emp_info.getName());
}
to
while (it.hasNext()) {
lp = (loginPojo) it.next();
emp_info = new EmployeeInfoPojo();//create object here
emp_info.setName(lp.getName());
System.out.println("Before "+emp_info.getName());
data.add(emp_info);
System.out.println("After "+emp_info.getName());
}
Because, as you are adding the same object to the ArrayList, its taking the value you last updated.

Your "emp_info" variable is being created outside the loop, which means that the one inside the loop is always the same instance. When you put that instance into a list, it's still the same instance. (Adding something to a list adds that instance, not a copy.)
Move this line:
EmployeeInfoPojo emp_info = new EmployeeInfoPojo();
immediately after this line:
lp = (loginPojo) it.next();
and you should find that your loop behaves more like you would expect it to.

You just create single object of EmployeeInfoPojo in method getEmployeeInfo. You need to initialize ep_info each time you iterate list.
iterator code should look like this -
while (it.hasNext()) {
lp = (loginPojo) it.next();
emp_info = new EmployeeInfoPojo
emp_info.setName(lp.getName());
System.out.println("Before "+emp_info.getName());
data.add(emp_info);
System.out.println("After "+emp_info.getName());
}
In your previous code you just operate on single object that is why when you change this object old value will override and ArrayList adding same object each time while looping.
Hence only last value is reflected in all objects(single object with three reference).

Briefly, you need to create a new EmployeeInfoPojo object within the while loop. Otherwise all you do is change the properties of a single object over and over and over again.

public ArrayList getEmpInfo(int id) {
ArrayList data = new ArrayList();
loginPojo lp=new loginPojo();
Session session = null;
SessionFactory sessionfactory = new Configuration().configure().buildSessionFactory();
session = sessionfactory.openSession();
String sql_query = "from loginPojo where id!=" + id;
Query query = session.createQuery(sql_query);
List<loginPojo> list = query.list();
Iterator it = list.iterator();
while (it.hasNext()) {
//you need to create new object or else it uses same object reference
EmployeeInfoPojo emp_info = new EmployeeInfoPojo();
lp = (loginPojo) it.next();
emp_info.setName(lp.getName());`enter code here`
System.out.println("Before "+emp_info.getName());
data.add(emp_info);
System.out.println("After "+emp_info.getName());
}
return data;
}

Related

JSF / Xpages how to clear sessionscopes?

I want to clear the current sessionscopes in my xpages application and reload them again. I have tried:
public Map<String, Object> sesScope;
this.sesScope = JSFUtil.getSessionScope();
clearMap(sesScope);
private void clearMap(Map<String, Object> map ){ // Get iterator for the keys
String methodName = new Object(){}.getClass().getEnclosingMethod().getName();
utils.printToConsole(this.getClass().getSimpleName().toString() + " " + methodName);
utils.printToConsole("-------before removing------");
utils.printToConsole(map.toString());
Set keyset = map.keySet();
Iterator itr = keyset.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
utils.printToConsole("--------After removing-------");
utils.printToConsole(map.toString());
}
Somehow I can not simply say sesScope.clear() since that would result in an error:
java.lang.UnsupportedOperationException at
com.sun.faces.context.BaseContextMap.clear(ExternalContextImpl.java:392)
How do I clear the sessionscope properly?
I do this to clear sessionScope:
for (final String key : JSFUtil.getSessionScope().keySet()) {
JSFUtil.getSessionScope().remove(key);
}

How to avoid duplicate values in a JComboBox?

cmbMake = new JComboBox();
cmbMake.addItem("**Please Select**");
Iterator i = products.entrySet().iterator();
while (i.hasNext())
{
Map.Entry me = (Map.Entry) i.next();
Product p = (Product) me.getValue();
if(!p.getMake().equals(cmbMake.getSelectedItem()))
{
cmbMake.addItem("" + p.getMake());
}
}
I have a class which holds product details is there anyway to stop the same make being added to the combo box?
You can try this code (I added some code to yours). The code gets the values of makes and stores them in a Set collection, and then populates the combo box.
cmbMake = new JComboBox();
cmbMake.addItem("**Please Select**");
Iterator i = products.entrySet().iterator();
Set<String> uniqueMakes = new HashSet<>(); // this stores unique makes
while (i.hasNext())
{
Map.Entry me = (Map.Entry) i.next();
Product p = (Product) me.getValue();
//if(! p.getMake().equals(cmbMake.getSelectedItem()))
//{
// cmbMake.addItem("" + p.getMake());
//}
uniqueMakes.add(p.getMake());
}
System.out.println(uniqueMakes); // this prints the makes
// Add makes to the combo box
for (String make : uniqueMakes) {
cmbMake.addItem(make);
}
Suggestions: You can use type parameters while using some of these, for example:
JComboBox<String> cmbMake = new JComboBox<>();
Iterator<Product> i = products.entrySet().iterator();
EDIT: Here are tutorials on using Set collection and using Generics.
EDIT (another way of coding the same functionality using functional-style programming):
cmbMake = new JComboBox<String>();
cmbMake.addItem("**Please Select**");
products.values()
.map(product -> product.getMake())
.collect(Collectors.toCollection(HashSet::new))
.forEach(make -> cmbMake.addItem(make));
Add all values to a Set and iterate over it :
for(Object o : new HashSet<>(products.values())){
Product p = (Product) o.getValue();
if(!p.getMake().equals(cmbMake.getSelectedItem())) {
cmbMake.addItem("" + p.getMake());
}
}
Assuming make is String, just create a set with all the different values and then add them to the ComboBox:
Set<String> productMakes = new HashSet<String>();
for (Map.Entry<KeyClass, Product> productEntry: products.entrySet()) {
productMakes.add(productEntry.getValue().getMake());
}
// How about sorting the items before adding them to the ComboBox?
List<String> sortedProductMakes = new ArrayList<String>(productMakes);
java.util.Collections.sort(sortedProductMakes);
for (String productMake : sortedProductMakes ) {
cmbMake.addItem(productMake);
}
Try this code,
cmbMake = new JComboBox();
cmbMake.addItem("**Please Select**");
Map products = null;
Iterator i = products.entrySet().iterator();
while (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
Product p = (Product) me.getValue();
Set<String> productSet = new HashSet<String>();
productSet.add(p.getMake());
if (!p.getMake().equals(cmbMake.getSelectedItem())) {
if (productSet.size() > 0) {
productSet.forEach(action -> {
cmbMake.addItem("" + action);
});
}
}
}

Strange behaviour with ArrayList

I'm in the process of building a basic database using csv files, and i'm currently testing the select function out when i ran into something strange.
private ArrayList<Record> selectField(String selectTerm)
{
Log.log("Selection " + selectTerm,2,"DB_io");
ArrayList<Record> ret = new ArrayList<Record>();
if (titleRow.values.contains(selectTerm))
{
Log.log("Adding values to " + selectTerm);
int ordinal = titleRow.values.indexOf(selectTerm);
Log.log("Ordinal " + ordinal);
List<String> tempList = new ArrayList<String>();
for (Record r : data)
{
List<String> tempList = new ArrayList<String>();
tempList.add(r.values.get(ordinal));
Record s = new Record(tempList);
ret.add(s);
tempList.clear();
}
Log.log("Number of records in ret " + ret.size());
for (Record t : ret)
{
Log.log(t.toString());
}
}
else
{
Log.log("keyField does not contain that field");
return null;
}
Log.log("Values " + ret.toString());
return ret;
}
When i do this, the part where it logs t.ToString() shows the record to be empty, whereas if i log it before tempList.clear(), it shows the record to be containing data like it should.
If i move the tempList declaration into the Record r : data loop, then it works fine and the Record t : ret loop works outputs the contents of the record like it should
Why is this?
Edit : Record class
public class Record
{
List<String> values = new ArrayList<String>();
public Record(List<String> terms)
{
this.values = terms;
}
public Record(String[] s)
{
this.values = Arrays.asList(s);
}
public String toString()
{
return values.toString();
}
}
Your Record instance holds a reference to the ArrayList instance you passed to its constructor. Therefore, when you call tempList.clear(), you clear the same List that your Record instance is holding a reference to.
You shouldn't call tempList.clear(), since you are creating a new ArrayList in each iteration of your loop anyway.
you are referencing object from more than one place and clear method is cleaning object by setting its reference to null:
instead of ret.add(s); you can use ret.add(s.clone());

Adding an Arraylist to another Arraylist in Java

I have seen this 2d Arraylist Question multiple times on SO, but don't understand why this doesn't work for my Language App.
I have an arraylist (called stage1) containing multiple arraylists (each is called entry) The System.out.println("In switch: this is entry" + entry); displays the database values correctly so I am sure that the query string elsewhere is correct (e.g. [In switch: this is entry[water, aqua, C:\Users\Username\Documents\NetBeansProjects\LanguageApp\src\Images\Categories\Food images\water.png])
But when I add entry to stage 1 and try to access it via stage1.get(0).get(0) I get the error "Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0" which is why I tested if stage1 is empty. The other trace statement confirms that stage1 is null even after entries are added.
ArrayList<List<String>> stage1 = new ArrayList<>();
ArrayList<String> entry = new ArrayList<>();
int count = 0;
//words is an Observable List of all words relating to a specific category and langage
for (Words k : words) {
String eng = k.getEnglishWord();
String trans = "";
switch (lang) {
case "spanish":
trans = k.getSpanishWord();
break;
case "french":
trans = k.getFrenchWord();
break;
case "german":
trans = k.getGermanWord();
break;
}
String pic = k.getPicture();
entry.add(eng);
entry.add(trans);
entry.add(pic);
System.out.println("This is entry" + entry);
stage1.add(entry);
entry.clear();
if(stage1.size()!=0){ System.out.println("Stage1 " + stage1.get(0).get(0));
}
else {System.out.println("IT IS NULL");}
}
You are using single object at each time that's why it gives index out of bounds exception
Just place your arraylist into the for loop
ArrayList<String> entry = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
//put you code here
ArrayList<String> entry = new ArrayList<String>();
entry.add("sd");
entry.add("sd");
entry.add("sd");
System.out.println("This is entry" + entry);
stage1.add(entry);
//entry.clear();
if(stage1.size()==0){ System.out.println("Stage1 " + stage1.get(0).get(0));
}
else {System.out.println("IT IS NULL");}
}
This will give's you desired output.
Every object in Java are reference Object. When you pass an object trought parameters of function, you pass the reference. If you modify the object inside or outside the method you will modify the object in and or out of the function.
I suggest you to take a look to it to clear your mind about all this.
Is Java "pass-by-reference" or "pass-by-value"?
Now, to solve your problem, you can reinstanciate you entre with entry = new ArrayList(); and the begiining of each loop and remove the entry.clear();.
ArrayList<List<String>> stage1 = new ArrayList<>();
ArrayList<String> entry = null;
int count = 0;
//words is an Observable List of all words relating to a specific category and langage
for (Words k : words) {
entry = new ArrayList<>();
String eng = k.getEnglishWord();
String trans = "";
switch (lang) {
case "spanish":
trans = k.getSpanishWord();
break;
case "french":
trans = k.getFrenchWord();
break;
case "german":
trans = k.getGermanWord();
break;
}
String pic = k.getPicture();
entry.add(eng);
entry.add(trans);
entry.add(pic);
System.out.println("This is entry" + entry);
stage1.add(entry);
//entry.clear();
if(stage1.size()!=0){ System.out.println("Stage1 " + stage1.get(0).get(0));
}
else {System.out.println("IT IS NULL");}
}

List iterator returns last rows only

Iterator<Account> entitiesItr = entities.iterator();
List<AccountSync> accountsList = new ArrayList<AccountSync>();
AccountSync accountsync = new AccountSync();
while (entitiesItr.hasNext()) {
Account account = (Account) entitiesItr.next();
accountsync.setAccountName(account.getName());
accountsList.add(accountsync);
System.out.println("1st-name->"+account.getName());
}
Iterator<AccountSync> it = accountsList.iterator();
while (it.hasNext()) {
AccountSync accountSync2 = (AccountSync) it.next();
System.out.println("2nd-name->"+accountSync2.getAccountName());
}
output:
1st-name->Sun
1st-name->Oracle
1st-name->google
...
1st-name->Yahoo
2nd-name->Yahoo
2nd-name->Yahoo
2nd-name->Yahoo
2nd-name->Yahoo
....50 times
2nd-name-> prints only last rows 50 times, while 1st-name-> it prints all 50 rows. Why does that happen?
It's because the first loop keep overwriting the same AccountSync.
Try this way:
AccountSync accountsync;
while (entitiesItr.hasNext()) {
accountsync = new AccountSync();
Account account = (Account) entitiesItr.next();
accountsync.setAccountName(account.getName());
accountsList.add(accountsync);
System.out.println("1st-name->"+account.getName());
}
in that case, each entity will have its own AccountSync instance properly.
you need to move
AccountSync accountsync = new AccountSync();
to inside of your while loop otherwise you are using the same one and simply updating it.

Categories

Resources