Devendra Lattu
Devendra Lattu

Reputation: 2802

Performing Integers operation on List<Objects>

I have a List of Objects which I want to convert to a List of Integers

List<Object> list = new ArrayList<>();

list.add("StringTest");
list.add(10);
list.add(5.9);
list.add(2.5f);
list.add(12L);
...            // different datatypes

List<Integer> result = new ArrayList<>();
// convert items from list and add to result

What could be a good custom implementation to add values from different datatypes of List<Object> to a List<Integer>

  1. Strings may be appended based on their length.
  2. Floating numbers needs to be rounded

I know standard implmentation on How to cast an Object to an int in java? but I am looking for a good structure to write a generic one.

Upvotes: 3

Views: 876

Answers (4)

Arthur Kushner
Arthur Kushner

Reputation: 99

If you want to add just numbers and don't process strings, than you can use this:

   List<Object> list = new ArrayList<>();

    list.add("StringTest");
    list.add(10);
    list.add(5.9);
    list.add(2.5f);
    list.add(12L);

    List<Integer> result = new ArrayList<>();

     list.stream().filter(element -> element instanceof Number)
            .map(Number.class::cast)
            .mapToDouble(Number::doubleValue)
            .mapToLong(Math::round)
            .mapToInt(Math::toIntExact) // can throw ArithmeticException if long value overflows an int
            .forEach(result::add);

If you also want to process string, than you need to replace string in list with int values of there length and then process as mentioned above.

Upvotes: 2

Vasu
Vasu

Reputation: 22422

You can use streams to process the list of Object types as shown in the below code (follow the comments):

//Collect all Number types to ints
List<Integer> output1 = list.stream().
    filter(val -> !(val instanceof String)).//filter non-String types
    map(val -> ((Number)val).floatValue()).//convert to Number & get float value
    map(val -> (int)Math.round(val)).//apply Math.round
    collect(Collectors.toList());//collect as List

//Collect all String types to int
List<Integer> output2 = list.stream().
      filter(val -> (val instanceof String)).//filter String types
       map(val -> (((String)val).length())).//get String lengths
       collect(Collectors.toList());//collect as List

//Now, merge both the lists
output2.addAll(output1);

Floating numbers needs to be rounded

You need to first convert the Number value to float using floatValue() method and then apply Math.round as shown above.

Upvotes: 2

castletheperson
castletheperson

Reputation: 33466

The instanceof operator would make this relatively simple.

public class Convert {
    public static int toInt(Object o) {
        if (o instanceof String) {
            return ((String)o).length();
        } else if (o instanceof Number) {
            return Math.round(((Number)o).floatValue());
        } else {
            return o.hashCode(); // or throw an exception
        }
    }
}

With Java 8, you could convert the values with a Stream.

List<Object> list = new ArrayList<>();

list.add("StringTest");
list.add(10);
list.add(5.9);
list.add(2.5f);
list.add(12L);

List<Integer> result = list.stream().map(Convert::toInt).collect(Collectors.toList());

Upvotes: 1

Courage
Courage

Reputation: 792

With this you can add to the Integer list at the same time when you add to the object list

final List<Integer> integerList=new ArrayList<Integer>();
List<Object> list=new ArrayList<Object>(){

  public boolean add(Object e) {
    if(e instanceof String){
      integerList.add(((String)e).length());
    }
    if (e instanceof Float){
      integerList.add(Math.round((float) e));
    }
    else{
      // other cases
    }
    return super.add(e);
  };
};
list.add("StringTest");
list.add(10);
list.add(5.9);
list.add(2.5f);
list.add(12L);

Upvotes: 0

Related Questions