Create an ArrayList with multiple object types?
Asked Answered
T

14

79

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.

Timothy answered 26/10, 2013 at 3:50 Comment(1)
Perhaps you want a Map<Integer, String> instead?Rhodarhodamine
K
95

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.

Kurland answered 26/10, 2013 at 3:53 Comment(6)
Yes, in my mind "make a custom model class with two parameters" is equal to a wrapper class with 2 constructors. So you can define a new list of type wrapper class: List<Wrapper> sections = new ArrayList <Wrapper>(); class Wrapper{ private Integer intValue=null; private String strValue=null; public Wrapper(String){...} public Wrapper(Integer){...} }Chainplate
What if your list also contains primitive data types?Birmingham
@735Tesla.. Making your own model class is the preferred way. You can include your primitive data types in the same and use a list of model class.Kurland
When not using final classes or primatives, I prefer to create an interface that describes what I'm going to do with the collection, and implement that interface (which may have just have a toString() method or even no methods) in either the original class or a wrapper class, and use that interface as the collection type. I find that to be a lot cleaner for future maintainers who can quickly understand why your generic collection has multiple types, how it's meant to be consumed, and how to add more types should it ever become necessary (which wouldn't even require modifying the collection).Trainband
You can also just use List sections = new ArrayList(); The default behavior of arraylist before generics was to take in any kind of Object and leave the casting up to the client.Chokecherry
This solution raising SonarQube issue as "Make 'sections' transient or serializable "Sidneysidoma
S
34

(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);
Selfsame answered 8/11, 2016 at 18:0 Comment(0)
C
19

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.

  1. 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;
    }}
    
  2. 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

Carotenoid answered 26/10, 2013 at 4:14 Comment(3)
This is a good example of a terrible code smell. One should never use ArrayList of objects. Usually it is better to redesign the code rather than using getClass/instanceof and downcasts to use the ArrayList.Hydromechanics
Genuinely looking for a better solution: How to sort different classes of objects by a shared property without building an ArrayList of a parent class or Interface and using getClass() or instanceof to compare - is there a better way?Subsume
One should never use ArrayList of objects. - @Hydromechanics can you please elaborate or reference the reason?Sogdian
K
8
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.

Kotick answered 21/11, 2015 at 11:23 Comment(0)
M
7

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!

Mythos answered 26/10, 2013 at 3:53 Comment(1)
yeah.. Mixed list is usually not recommended. I might result into ClassCastExceptions later on.Kurland
L
7

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
}
Lewse answered 5/4, 2014 at 16:40 Comment(0)
O
4

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>

Objurgate answered 12/12, 2016 at 13:39 Comment(0)
P
2

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){

} 
Pl answered 26/10, 2013 at 3:57 Comment(3)
And then be forced to use instanceof if you want to use the item? No thanks.Mythos
@HovercraftFullOfEels If we don't know the type we have to use instanceof. any other way?Pl
Yes, re-design the program so you aren't forced to collect oranges with orangutans. The original question has a strong code smell to it, that shouts (at least to me) that the design is off if it requires such a construct.Mythos
U
2

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.

Uria answered 26/10, 2013 at 4:18 Comment(1)
You could use getClass() or instanceof to retrieve information about the type of objects at runtime. That way, you could loop through the ArrayList and perform a different operation based on the type of the object.Glyconeogenesis
A
2

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);
        }
    }

}
Applied answered 5/10, 2015 at 14:59 Comment(1)
Using raw types (as in ArrayList) is no better than having a generic parameter of Object (as in ArrayList<Object>), and is generally discouraged. (It also introduces a couple non-obvious edge cases.)Beedon
A
0

Of all the ways, this was the one I chose (in 2024), so I post here (10y OP) because I came across this looking for a solution, and didn't see the one below.

public static void DoMultiLists() {
        Map<String, Double> mapSentiment = new HashMap<String, Double>();
        List<Map<String, Double>> lstArticles = new ArrayList<Map<String, Double>>();   
}

-For each topic, there are from 0 to ? 'articles' (think outer List() above). -Inside those articles are words (content) used w/NLP to create a sentiment score (Double), and a 'rating' string ('relevant', 'neutral, 'irrelevant', ...). This the inner Map().

Each article (class) can now have it's own List of Maps that store the sentiment data, to later be put in a DB, without complications. Java22

Adust answered 15/4, 2024 at 20:52 Comment(0)
B
-1

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)):
Bugger answered 18/3, 2020 at 21:47 Comment(1)
This is incorrect. The question is about creating a list that contains strings OR integers. Your answer gives the reader a list containing TUPLES that hold a string AND an integer.Lithoid
I
-1

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
Iambus answered 2/6, 2021 at 14:53 Comment(1)
This use of raw types comes at the expense of type safety. You will need to use a lot of code that uses instanceof to check what you're getting from the list. Generics were invented to have containers of a certain type only. See also item 26 in Effective Java: "Don't use raw types".Cesena
S
-3

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

Skinnydip answered 30/5, 2016 at 9:10 Comment(2)
Why was this solution accepted when it doesn't answer the question about an array of multiple object types. All you've done here is used the same object type ArrayList<Student>. Downvoted.Certie
What if i want to add objects other then Wrapper like Custom object1 , Custom object2. Call it's method without type casting.Mediaeval

© 2022 - 2025 — McMap. All rights reserved.