Multiple NULL addition into a List in Java - java

I have 2 lists and want to copy some element from one to another, i.e. there are old and new employees list I need to union 2 lists and delete the elements that include to the old list but not include in the new one.
I could solve the part of getting the union and intersection by using TreeSet and override the equals and hashcode functions of the Employees class....
Now, I want to exclude the elements that are in the old but not in the new and add them to the "deletedList"....which I got "ConcurrentModificationException"
I tried this instead of "iterator" but the same result: for(Employees e : employeesListDB)
Also I tried "CopyOnWriteArrayList" instead of "ArrayList" but no change!!
but the problem now that at the initialization of the empty list "deletedList" it is filled with multiple null elements before the add function!
Here is the code:
List<Employees> employeesListDB = this.findAll();
Set<Employees> empSet = new TreeSet<Employees>(new EmployeeComparator());
empSet.addAll(employeesList);
List<Employees> deletedList = new ArrayList<Employees>();
Employees e = new Employees();
ListIterator<Employees> itr = employeesListDB.listIterator();
for(itr.hasNext()) {
e = (Employees)itr.next();
if(!empSet.contains(e)) {
deletedList.add(e);
}
}
A counter Example:
The oldlist "employeesListDB" the employees list from the database:
[
{
"email":"mariam.moustafa#x.com"
},
{
"email":"sara.ahmed#x.com"
},
{
"email":"ali.hassan#x.com"
},
{
"email":"hoosen.imam-ally#x.com"
},
{
"email":"allan.randall#x.com"
},
{
"email":"nishaan.maharaj#x.com"
}
]
The new list to be added:
[
{
"email":"ali.moustafa#x.com"
},
{
"email":"sara.ahmed#x.com"
},
{
"email":"emad.hamed#x.com"
}
]
The deleted list that I want:
[
{
"email":"mariam.moustafa#x.com"
},
{
"email":"ali.hassan#x.com"
},
{
"email":"hoosen.imam-ally#x.com"
},
{
"email":"allan.randall#x.com"
},
{
"email":"nishaan.maharaj#x.com"
}
]
Sara mail will be updated...
Employee class has two fields {id,email} the new list (the list to be added to the db) is a list of only emails, id field are not recognized yet but the old list has the complete bean fields ...to compare between these 2 list I should override the Comparator to ignore the id field; Finding duplicates in a List ignoring a field
JUST I need to know, why when I use set.add operation, it adds the unique emails only! the original size of the list was 36 elements after adding it into a set it becomes only 16!!
Set<Employees> oldSet = new TreeSet<Employees>(new EmployeeComparator());
oldSet.addAll(employeesListDB);
Set<Employees> newSet = new TreeSet<Employees>(new EmployeeComparator());
newSet.addAll(employeesList);
Set<Employees> deleted = Sets.difference(oldSet, newSet);

As I understand, you need all elements that are contained by old set and not contained by new set.
For this purpose you can use Guava Sets#difference method:
Set<Employees> deleted = Sets.difference(oldSet, newSet);
Test with your data:
Set<String> oldEmployees = Sets.newHashSet("mariam.moustafa#x.com", "sara.ahmed#x.com", "ali.hassan#x.com", "hoosen.imam-ally#x.com", "allan.randall#x.com", "nishaan.maharaj#x.com");
Set<String> newEmployees = Sets.newHashSet("ali.moustafa#x.com", "sara.ahmed#x.com", "emad.hamed#x.com");
Set<String> diff = Sets.difference(oldEmployees, newEmployees);
System.out.println(diff);
Result:
[nishaan.maharaj#x.com, mariam.moustafa#x.com, ali.hassan#x.com, allan.randall#x.com, hoosen.imam-ally#x.com]

Here is a core Java solution using 2 simple steps:
[1] - Create a set setOld which contains the first set of emails
[2] - Subtract from setOld a new set of emails setNew
Set oldSet<String> = new HashSet<String>(); // original set of email addresses
oldSet.add("mariam.moustafa#x.com");
oldSet.add("sara.ahmed#x.com");
oldSet.add("ali.hassan#x.com");
oldSet.add("hoosen.imam-ally#x.com");
oldSet.add("allan.randall#x.com");
oldSet.add("nishaan.maharaj#x.com");
Set newSet<String> = new HashSet<String>(); // new set of email addresses
newSet.add("ali.moustafa#x.com");
newSet.add("sara.ahmed#x.com");
newSet.add("emad.hamed#x.com");
for (String s : newSet) {
oldSet.remove(s); // this will only remove the element if found
}
// display new contents of oldSet
for (String s : oldSet) {
System.out.println(s);
}
Output:
mariam.moustafa#x.com
ali.hassan#x.com
hoosen.imam-ally#x.com
allan.randall#x.com
nishaan.maharaj#x.com

Try it this way (Made a small TestCase):
private static Employee createEmployee(String string) {
Employee employee = new Employee();
employee.setEmail(string);
return employee;
}
public static void main(String[] args) {
List<String> newMails = new ArrayList<>();
List<Employee> oldList = new ArrayList<>();
oldList.add(createEmployee("mariam.moustafa#x.com"));
oldList.add(createEmployee("sara.ahmed#x.com"));
oldList.add(createEmployee("ali.hassan#x.com"));
oldList.add(createEmployee("hoosen.imam-ally#x.com"));
oldList.add(createEmployee("allan.randall#x.com"));
oldList.add(createEmployee("nishaan.maharaj#x.com"));
newMails.add("ali.moustafa#x.com");
newMails.add("sara.ahmed#x.com");
newMails.add("emad.hamed#x.com");
List<Employee> delete = new ArrayList<>();
Set<String> removedMails = new HashSet<>();
for (Employee emp : oldList) {
if (!newMails.contains(emp.getEmail())) {
delete.add(emp);
}
removedMails.add(emp.getEmail());
}
newMails.removeAll(removedMails);
// remove emploeyees in delete
oldList.removeAll(delete);
// Create employee for left MAils
for (String newMail : newMails) {
oldList.add(createEmployee(newMail));
}
//Old and new Employees
for (Employee emp : oldList) {
System.out.println(emp.getEmail());
}
}
simple Employee class:
class Employee {
String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
output:
sara.ahmed#x.com
ali.moustafa#x.com
emad.hamed#x.com

the empty list filled with multiple null elements before the add
function!
This is becuase you're using the ArrayList which contains the following constant:
private static final int DEFAULT_CAPACITY = 10;
Which mean when you create the ArrayList<T> with the new operator you actually create an Array of T which contains 10 nulls (It's contained as private transient Object[] elementData field).
The JLS said:
Every variable in a program must have a value before its value is
used:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10.2):
[...]
For all reference types (§4.3), the default value is null.

Use List removeAll method. You will need to override equals method in your Employees class. PFB sample snippet based on employee id, you will need to modify it to fit based on email id:
import java.util.*;
public class StringArray {
public static void main(String args[]) {
List<Employee> oldList = new ArrayList<Employee>();
oldList.add(new Employee(1));
oldList.add(new Employee(2));
oldList.add(new Employee(3));
oldList.add(new Employee(4));
List<Employee> newList = new ArrayList<Employee>();
newList.add(new Employee(3));
newList.add(new Employee(4));
newList.add(new Employee(5));
newList.add(new Employee(6));
oldList.removeAll(newList);
System.out.println("Printing delete list");
for (Employee employee : oldList)
System.out.println(employee);
System.out.println("Printing updated list");
for (Employee employee : newList)
System.out.println(employee);
}
}
public class Employee {
private int id;
public Employee(int id) {
super();
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Override
public String toString() {
return "Employee [id=" + this.id + "]";
}
#Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Employee))
return false;
Employee c = (Employee) o;
return this.id == c.id;
}
}

Related

Filter/ remove all null values of all elements using java8

I am trying to understand Java 8 features and use:
Below I want to filter null values from list
I know that using .filter(n->n != null) we can filter the null from list.
But I want to know that what to do if any element is null.
I also know that we can simply do like .filter(n-> n.empName != null) but what if I have many fields where types are not known while filtering.
Can we loop list inside filter and check for n elements each is null or not? Or please guide me an approach. Also when we convert list to map of null values are found it will throw error.
How do we do this using java8?
Employee[] arrayOfEmps = {
new Employee(1, "Jeff Bezos", 100000.0),
new Employee(5, "Vijay", 700000.0),
new Employee(2, "Bill Gates", 200000.0),
new Employee(4, "Shweta Oza", 500000.0),
new Employee(0, null, 400000.0),
null,
new Employee(3, "Mark Zuckerberg", 300000.0)
};
//Array -> Stream
Stream<Employee> streamEmp = Stream.of(arrayOfEmps);
streamEmp.forEach(s->System.out.println(s.empID+" "+s.empName+" "+s.salary));
//Array -> List
List<Employee> empList = Arrays.asList(arrayOfEmps);
empList.forEach(System.out::println);
//List -> Stream
empList.stream();
Map<Integer, String> map = new HashMap<Integer, String>();
for(Employee e : empList) {
map.put(e.empID, e.empName);
}
System.out.println(map);
Map<Integer, String> map8 = new HashMap<Integer, String>();
map8 = empList.stream().filter(n->n!=null).collect(Collectors.toMap(Employee::getEmpID, Employee::getEmpName));
System.out.println(map8); //error
I did it as follows just to get rid of null
List<Employee> dd = empList.stream().filter(currentEmp ->
{
if (currentEmp == null)
{
return false;
}
if (currentEmp.getEmpName() == null)
{
return false;
}
if(currentEmp.getEmpID()==0) {
return false;
}
if(currentEmp.getSalary()==0) {
return false;
}
return true;
// .. etc.
}).collect(Collectors.toList());
for(int i=0;i<dd.size();i++) {
System.out.println(dd.get(i).empName.toString());
}
map8 = dd.stream().collect(Collectors.toMap(Employee::getEmpID, Employee::getEmpName));
System.out.println(map8);
As you said, null Objects can be filtered. So the problem is objects of unknown class with null fields, like Employee, Manager, External. One could do it with reflection but that is ugly and slow. Better ensure in all those classes that they cannot have those null fields: Objects.requireNonNull. This ensures a fail-fast, so actually programmer testing will ensure correct code
class Employee {
public Employee(String name) {
Objects.requireNonNull(name);
When using some frameworks, one can use an annotation, like #NonNull for compile time code analysis.
public Employee(#NonNull String name) {
And then one may guard to have the classes fields unassigned - when they are immutable - by final (constant fields):
private final String name;
public Employee(String name) {
this.name = name; // Still name might be null, so:
Objects.requireNonNull(name);
Not a perfect solution.
filter() takes as an argument a lambda expression, you could do whatever you want in it, as long as you return a boolean.
Example:
empList.stream().filter(currentEmp ->
{
if (currentEmp == null)
{
return false;
}
if (currentEmp.getName().trim().equals(""))
{
return false;
}
// .. etc.
}).collect(Collectors.toList());
Regarding the second question, can you provide the error?
i want to know that what to do if any element is null
You skip it mostly.
What if I have many fields where types are not known while filtering, can we loop list inside filter and check for n elements each is null or not?
You will have the information regarding types of fields ahead of time, since java is typed language.
The concept of filtering is to include or exclude some portion of data(obviously from alot more) and since all are objects in java you can check for null without a problem(except premitives).
I will use your example with some modifications:
Employee[] arrayOfEmps = {
new Employee(1, "Jeff Bezos", 100000.0),
new Employee(5, "Vijay", 700000.0),
new Employee(2, "Bill Gates", 200000.0),
new Employee(4, "Shweta Oza", 500000.0),
new Employee(0, null, 400000.0),
null, // note here
new Employee(3, "Mark Zuckerberg", 300000.0)
};
So basically what you have to do for filtering null would be:
x.filter(Objects::nonNull).x.... or x.filter(val -> val != null).x...
More or less the your example will look like:
import java.util.*;
import java.util.stream.*;
public class Main
{
public static void main(String[] args) {
Employee[] arrayOfEmps = {
new Employee(1, "Jeff Bezos", 100000.0),
new Employee(5, "Vijay", 700000.0),
new Employee(2, "Bill Gates", 200000.0),
new Employee(4, "Shweta Oza", 500000.0),
new Employee(0, null, 400000.0),
null, // note here
new Employee(3, "Mark Zuckerberg", 300000.0)
};
List<Employee> result = Arrays.asList(arrayOfEmps).stream().filter(Objects::nonNull).collect(Collectors.toList());
System.out.println(result);
}
}
class Employee {
private int id;
private String name;
private double salary;
Employee(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
#Override
public String toString() {
return "[id: " + this.id +" name: " + this.name + "salary: "+ this.salary + "]";
}
}

How do I enhance this Duplicate objects from List method using Java 8? The Object in the List is nested that is what makes this complex

I am trying to filter out the duplicate Objects from a List of Objects.
I am trying to remove the duplicate objects from the main List passed to the method and create another List containing those duplicate copies. This problem becomes complex as The Main Object in the List contains objects within it with which we need to check the duplicate.
My requirement is somewhat as described below:
List<RateContract> "rateContractListWithOptions" contains two objects of RateContract:
[
RateContract1 :{
Rate :{tarifId: 1 //other variables will also be defined}
Contract : {contractId:1}
},
RateContract2 :{
Rate :{tarifId: 2}
Contract : {contractId:1}
}
]
Duplicate Rates will be checked using the equals method in the Rate class
At the end of the functions Processing
"rateContractListWithOptions" this will have only one object of RateContract in list. maybe - [RateContract1 :{
Rate :{tarifId: 1 //other variables will also be defined}
Contract : {contractId:1}
}]
and "duplicateRateContracts" this will contain the duplicate
[RateContract2 :{
Rate :{tarifId: 2}
Contract : {contractId:1}
}]
I have written filterDuplicateRatesInSameContracts method, how do I
enhance this?
public class RateContract implements Serializable {
private Rate rate = null;
private Contract contract = null;
private Map<Integer,List<Option>> optionMap = new HashMap<>();
private Map<String, String> otherInformationMap = new HashMap<>();
}
public class Rate implements Serializable {
private String promoCode = null;
private String tiers_groupe_id = null;
private String business_model = null;
private Integer tarifId = null;
private Integer ageMin = null;
private Integer ageMinAbs = null;
private String fuelType = null;
#Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Rate rate = (Rate) o;
return Objects.equals(promoCode, rate.promoCode) &&
Objects.equals(business_model, rate.business_model) &&
!Objects.equals(tarifId, rate.tarifId) &&
Objects.equals(ageMin, rate.ageMin) &&
Objects.equals(ageMinAbs, rate.ageMinAbs) &&
Objects.equals(fuelType, rate.fuelType) &&
Objects.equals(ageMax, rate.ageMax) &&
Objects.equals(ageMaxAbs, rate.ageMaxAbs);
}
#Override
public int hashCode() {
return Objects.hash(promoCode, business_model, tarifId, ageMin, ageMinAbs, fuelType, ageMax, ageMaxAbs);
}
}
public class Contract implements Serializable {
private Integer contractId;
......
}
//The filtering Logic method is::
private List<RateContract> filterDuplicateRatesInSameContracts(List<RateContract> rateContractListWithOptions) {
Map<Integer, List<RateContract>> rateContractMap = new HashMap<>();
rateContractListWithOptions.forEach(rateContract -> {
rateContractMap.computeIfAbsent(rateContract.getContract().getContractId(), k -> new ArrayList<>()).add(rateContract);
});
List<RateContract> duplicateRateContracts = new ArrayList<>();
rateContractMap.forEach((contract, rateContracts) -> {
if (rateContracts.size() > 1) {
for (RateContract rateContract : rateContracts) {
boolean isFound = false;
for (RateContract dupliRateContract : duplicateRateContracts) {
if (rateContract.getRate().equals(dupliRateContract.getRate())) {
isFound = true;
break;
}
}
if (!isFound) duplicateRateContracts.add(rateContract);
}
}
});
rateContractListWithOptions.removeAll(duplicateRateContracts);
return duplicateRateContracts;
}
I'm interpreting your question as 'how do I move to a separate list all contracts in a list that have the same rate as an earlier item in the list'?
If so:
List<RateContract> duplicates = new ArrayList<>();
Set<Rate> rates = new HashSet<>();
Iterator<RateContract> iterator = contracts.iterator();
while (iterator.hasNext()) {
RateContract contract = iterator.next();
if (!rates.add(contract.getRate())) {
iterator.remove();
duplicates.add(contract);
}
}
Note that this uses Iterator so that you can remove the contracts with matching rates as you move through the list. An alternative would be to collect them in the duplicates list and then remove them afterwards. Both would work.

Hierarchical Data to arrayList using recursion. (Java)

I have hierarchical data in MySQL of employees and their subordinates as shown here There is a joining column 'managerID' which references to the employee ID in the same column.
My objective is to recursively go through this data and add it all to an arrayList which would end up looking like this:
[Tom [Hanna [George [Chris], Rachel]]]
But there is a logic problem in my java function:
public void getList(String employeeName, ArrayList<Object> arrayList) {
// Initialise the arrayList the first time
if (arrayList == null) {
arrayList = new ArrayList<>();
}
// Using the string provided, I have found the employee
Employee employee = employeeRepository.findByName(employeeName);
// adding employee to the list
arrayList.add(employee);
// Getting list of employee's subordinates
List<Employee> subordinates = employee.getSubordinates();
// Checking if employee has subordinates
if (subordinates != null) {
// Iterate through each of their subordinates and call recursive function
for (int i = 0; i < subordinates.size(); i++) {
ArrayList<Object> subOrdinateDetails = new ArrayList<>();
// If the subordinate has subordinates, use recursion
if (subordinates.get(i).getSubordinates() != null) {
getList(subordinates.get(i).getName(), subordinatesDetails);
}
// Adding this list to the original arrayList
arrayList.add(subOrdinateDetails);
}
System.out.println(arrayList.toString());
}
}
The toString method at the end of the method does not print what I wanted above, instead it prints:
[Chris]
[George, [Chris]]
[Rachel]
[Hanna, [George, [Chris]], [Rachel]]
[Tom, [Hanna, [George, [Chris]], [Rachel]]]
While trying to debug it, I tried to get the first index of the arrayList, to understand what it was here is what it printed:
Chris
George
Rachel
Hanna
Tom
As you can tell, I am new to java, and I have failed debugging my code. If you could point out my mistake, I will be very grateful.
You can simply do it like this.
public class Employee {
private final String name;
private final List<Employee> subordinates;
public Employee(String name, List<Employee> subordinates) {
super();
this.name = name;
this.subordinates = subordinates;
}
public String getName() {
return name;
}
public List<Employee> getSubordinates() {
return subordinates;
}
public void print() {
System.out.println(this.name);
this.subordinates.forEach(emp -> {
emp.print();
});
}
}
public class EmployeeTest {
public static void main(String[] args) {
Employee chris = new Employee("chris", new ArrayList<>());
Employee george = new Employee("george", Arrays.asList(chris));
Employee rachell = new Employee("rachell", new ArrayList<>());
Employee hannah = new Employee("hannan", Arrays.asList(george, rachell));
Employee tom= new Employee("tom",Arrays.asList(hannah));
tom.print();
}
}
The trick in the recursion is each time it prints out the current employee, before printing any of it's subordinates as you can see in the method. I'll leave it to you to come up with the brackets if needed.

Create an ArrayList with multiple object types?

How do I create an ArrayList with integer and string input types? If I create one as:
List<Integer> sections = new ArrayList <Integer>();
that will be an Integer type ArrayList.
If I create one as:
List<String> sections = new ArrayList <String>();
that will be of String type.
How can I create an ArrayList which can take both integer and string input types?
Thank you.
You can make it like :
List<Object> sections = new ArrayList <Object>();
(Recommended) Another possible solution would be to make a custom model class with two parameters one Integer and other String. Then using an ArrayList of that object.
(1)
ArrayList<Object> list = new ArrayList <>();`
list.add("ddd");
list.add(2);
list.add(11122.33);
System.out.println(list);
(2)
ArrayList arraylist = new ArrayList();
arraylist.add(5);
arraylist.add("saman");
arraylist.add(4.3);
System.out.println(arraylist);
You can use Object for storing any type of value for e.g. int, float, String, class objects, or any other java objects, since it is the root of all the class. For e.g.
Declaring a class
class Person {
public int personId;
public String personName;
public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}}
main function code, which creates the new person object, int, float, and string type, and then is added to the List, and iterated using for loop. Each object is identified, and then the value is printed.
Person p = new Person();
p.setPersonId(1);
p.setPersonName("Tom");
List<Object> lstObject = new ArrayList<Object>();
lstObject.add(1232);
lstObject.add("String");
lstObject.add(122.212f);
lstObject.add(p);
for (Object obj : lstObject) {
if (obj.getClass() == String.class) {
System.out.println("I found a string :- " + obj);
}
if (obj.getClass() == Integer.class) {
System.out.println("I found an int :- " + obj);
}
if (obj.getClass() == Float.class) {
System.out.println("I found a float :- " + obj);
}
if (obj.getClass() == Person.class) {
Person person = (Person) obj;
System.out.println("I found a person object");
System.out.println("Person Id :- " + person.getPersonId());
System.out.println("Person Name :- " + person.getPersonName());
}
}
You can find more information on the object class on this link Object in java
List<Object> list = new ArrayList<>();
list.add(1);
list.add("1");
As the return type of ArrayList is object, you can add any type of data to ArrayList but it is not a good practice to use ArrayList because there is unnecessary boxing and unboxing.
You could create a List<Object>, but you really don't want to do this. Mixed lists that abstract to Object are not very useful and are a potential source of bugs. In fact the fact that your code requires such a construct gives your code a bad code smell and suggests that its design may be off. Consider redesigning your program so you aren't forced to collect oranges with orangutans.
Instead -- do what G V recommends and I was about to recommend, create a custom class that holds both int and String and create an ArrayList of it. 1+ to his answer!
Create your own class which stores the string and integer, and then make a list of these objects.
class Stuff {
private String label;
private Integer value;
// Constructor
public void Stuff(String label, Integer value) {
if (label == null || value == null) {
throw NullPointerException();
}
this.label = label;
this.value = value;
}
// getters
public String getLabel() {
return this.label;
}
public Integer getValue() {
return this.value;
}
}
Then in your code:
private List<Stuff> items = new ArrayList<Stuff>();
items.add(new Stuff(label, value));
for (Stuff item: items) {
doSomething(item.getLabel()); // returns String
doSomething(item.getValue()); // returns Integer
}
It depends on the use case. Can you, please, describe it more?
If you want to be able to add both at one time, than you can do the which is nicely described by #Sanket Parikh. Put Integer and String into a new class and use that.
If you want to add the list either a String or an int, but only one of these at a time, then sure it is the List<Object>
which looks good but only for first sight! This is not a good pattern. You'll have to check what type of object you have each time you get an object from your list. Also This type of list can contain any other types as well.. So no, not a nice solution. Although maybe for a beginner it can be used. If you choose this, i would recommend to check what is "instanceof" in Java.
I would strongly advise to reconsider your needs and think about maybe your real nead is to encapsulate Integers to a List<Integer> and Strings to a separate List<String>
Can i tell you a metaphor for what you want to do now? I would say you want to make a List wich can contain coffee beans and coffee shops. These to type of objects are totally different! Why are these put onto the same shelf? :)
Or do you have maybe data which can be a word or a number? Yepp! This would make sense, both of them is data! Then try to use one object for that which contains the data as String and if needed, can be translated to integer value.
public class MyDataObj {
String info;
boolean isNumeric;
public MyDataObj(String info){
setInfo(info);
}
public MyDataObj(Integer info){
setInfo(info);
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
this.isNumeric = false;
}
public void setInfo(Integer info) {
this.info = Integer.toString(info);
this.isNumeric = true;
}
public boolean isNumeric() {
return isNumeric;
}
}
This way you can use List<MyDataObj> for your needs. Again, this depends on your needs! :)
Some edition: What about using inharitance? This is better then then List<Object> solution, because you can not have other types in the list then Strings or Integers:
Interface:
public interface IMyDataObj {
public String getInfo();
}
For String:
public class MyStringDataObj implements IMyDataObj {
final String info;
public MyStringDataObj(String info){
this.info = info;
}
#Override
public String getInfo() {
return info;
}
}
For Integer:
public class MyIntegerDataObj implements IMyDataObj {
final Integer info;
public MyIntegerDataObj(Integer info) {
this.info = info;
}
#Override
public String getInfo() {
return Integer.toString(info);
}
}
Finally the list will be: List<IMyDataObj>
You don't know the type is Integer or String then you no need Generic. Go With old style.
List list= new ArrayList ();
list.add(1);
list.add("myname");
for(Object o = list){
}
You can always create an ArrayList of Objects. But it will not be very useful to you. Suppose you have created the Arraylist like this:
List<Object> myList = new ArrayList<Object>();
and add objects to this list like this:
myList.add(new Integer("5"));
myList.add("object");
myList.add(new Object());
You won't face any problem while adding and retrieving the object but it won't be very useful.
You have to remember at what location each type of object is it in order to use it. In this case after retrieving, all you can do is calling the methods of Object on them.
You can just add objects of diffefent "Types" to an instance of ArrayList. No need create an ArrayList. Have a look at the below example,
You will get below output:
Beginning....
Contents of array: [String, 1]
Size of the list: 2
This is not an Integer String
This is an Integer 1
package com.viswa.examples.programs;
import java.util.ArrayList;
import java.util.Arrays;
public class VarArrayListDemo {
#SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
System.out.println(" Beginning....");
ArrayList varTypeArray = new ArrayList();
varTypeArray.add("String");
varTypeArray.add(1); //Stored as Integer
System.out.println(" Contents of array: " + varTypeArray + "\n Size of the list: " + varTypeArray.size());
Arrays.stream(varTypeArray.toArray()).forEach(VarArrayListDemo::checkType);
}
private static <T> void checkType(T t) {
if (Integer.class.isInstance(t)) {
System.out.println(" This is an Integer " + t);
} else {
System.out.println(" This is not an Integer" + t);
}
}
}
Just use Entry (as in java.util.Map.Entry) as the list type, and populate it using (java.util.AbstractMap’s) SimpleImmutableEntry:
List<Entry<Integer, String>> sections = new ArrayList<>();
sections.add(new SimpleImmutableEntry<>(anInteger, orString)):
For me this method works perfectly fine in jdk 16
import java.util.ArrayList;
public class Array {
public static void main(String[] args) {
ArrayList arrayList= new ArrayList();
arrayList.add("alien");
arrayList.add(1);
arrayList.add(0,'b');
System.out.println(arrayList);
System.out.println((arrayList.get(0)) instanceof Integer);
}
}
Output
[b, alien, 1]
false
User Defined Class Array List Example
import java.util.*;
public class UserDefinedClassInArrayList {
public static void main(String[] args) {
//Creating user defined class objects
Student s1=new Student(1,"AAA",13);
Student s2=new Student(2,"BBB",14);
Student s3=new Student(3,"CCC",15);
ArrayList<Student> al=new ArrayList<Student>();
al.add(s1);
al.add(s2);
al.add(s3);
Iterator itr=al.iterator();
//traverse elements of ArrayList object
while(itr.hasNext()){
Student st=(Student)itr.next();
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
}
}
class Student{
int rollno;
String name;
int age;
Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}
}
Program Output:
1 AAA 13
2 BBB 14
3 CCC 15

How to insert Java object into an ArrayList?

I have a problem trying to insert a calculated result into an ArrayList of Student's list of results.
It goes like this.
An ArrayList (called FullList) holds a list of Student objects.
A Student object has a name (as a String) and a resultslist (as an ArrayList).
When i receive a Result object, it comes with a name (as a String) and result (as a Integer).
I want to insert this Result object into the Student object's resultlist.
However, the student names are not defined upfront but deduced upon the receipt of a Results object.
That is to say, if there is no Student object in FullList, the Result object will trigger the creation of a Student object and insert itself into the Student object's resultslist.
Then the created Student object will be inserted into FullList.
I have written the code below but I'm getting multiple insertions of the same tag into FullList instead of insertion of multiple results into each tag.
Q1: I can't figure out what's wrong! Need a mind prick from the Gurus!
Q2: I will be using the following code for up to 90,000 students. Is this a feasible way of housing student results?
class Result {
String name;
int result;
public Result(String name, int result) {
this.name = name;
this.result = result;
}
/* start - Getting hungup over this method
* Something is wrong here and i don't know what it is
*/
public void setResult(ArrayList <Student> fullList) {
for (Student s : fullList) {
if (s.getName().equalsIgnoreCase(this.name)) {
s.setResult(this);
}
else { /* enters here if Student does not exist in fullList */
Student s = new Student(this.name); /* create new student */
s.setResult(this); /* insert result into Student's resultslist */
fullList.add(s); /* add Student into fullList */
}
}
}
/* end */
public String getName() {
return this.name;
}
}
class Student {
String name;
ArrayList <Result> resultslist;
public Student(String name) {
this.name = name;
resultslist = new ArrayList <Result> ();
}
public void setResult(Result result) {
this.resultslist.add(result);
}
public String getName() {
return this.name;
}
}
class StudentResults {
public static void main (String [] args) {
ArrayList <Student> FullList = new ArrayList <Student> ();
Result r1 = new Result("John", 12);
Result r2 = new Result("Jamie", 99);
Result r3 = new Result("John", 69);
Result r4 = new Result("Jacque", 56);
Result r5 = new Result("Jacque", 100);
Result r6 = new Result("Jamie", 100);
r1.setResult(FullList);
r2.setResult(FullList);
r3.setResult(FullList);
r4.setResult(FullList);
r5.setResult(FullList);
r6.setResult(FullList);
}
}
For each student in the list, you're inserting a new student if this student doesn't have the same name as the result to insert:
for (Student s : fullList) {
if (s.getName().equalsIgnoreCase(this.name)) { // current student has same name as result
s.setResult(this);
}
else { // current student doesn't have the same name as result
Student s = new Student(this.name);
s.setResult(this);
fullList.add(s);
}
}
The above should be written as:
Student s = findStudentWithName(fullList, this.name);
if (s == null) {
Student s = new Student(this.name);
s.setResult(this);
fullList.add(s);
}
else {
s.setResult(this);
}
And the findStudentWithName method would look like this:
private Student findStudentWithName(List<Student> students, String name) {
for (Student s : students) {
if (s.getName().equalsIgnoreCase(name)) {
return s;
}
}
// no student found.
return null;
}
Use Map/HashMap in place of List as:
Map<String, Student> fullStudents= new HashMap<Student>();
and use it as:
public void setResult(Map<String, Student> fullMap) {
Student s = fullMap.get(this.name.toLowerCase());
if(s == null){
s = new Student(this.name);
fullMap.put(this.name.toLowerCase(), s);
}
s.setResult(this);
}
Its much simpler and cleaner.
Also to get the list of Students any time, you can simply do:
List<Student> fullList = fullMap.values();

Categories