Reputation: 165
I have a list of numbers from a csv file that I have exported to an ArrayList. Now, the thing is that my ArrayList is in String and not in double. I have tried using
ArrayList<Double> arr = new ArrayList<Double>();`
but it gave me an error.
I want to remove any number in the ArrayList that is less than 0.1. Here is my code:
public class Example1
{
public static void main(String[] args) throws InvalidFormatException, IOException{
ArrayList arr=new ArrayList();
File f=new File("C:\\java\\marchcalllast.csv");
Scanner in=new Scanner(f).useDelimiter(",");
while(in.hasNext())
{
arr.add(in.next());
}
for (int i = 0; i < arr.size(); i++){
Double item = Double.valueOf(arr.get(i));
if (item < 0.1) {
arr.remove(i);
}
}
System.out.println(arr);
It gives me the following error:
Error: no suitable method found for valueOf(java.lang.Object) method java.lang.Double.valueOf(double) is not applicable (actual argument java.lang.Object cannot be converted to double by method invocation conversion) method java.lang.Double.valueOf(java.lang.String) is not applicable (actual argument java.lang.Object cannot be converted to java.lang.String by method invocation conversion)
Upvotes: 2
Views: 1168
Reputation: 2681
Why create a new List or filter/modify one when you filter at read time:
public class FilterDouble {
public static void main(String[] args) throws IOException {
File file = new File("C:\\java\\marchcalllast.csv");
Scanner in = new Scanner(file).useDelimiter(",");
List<Double> list = new ArrayList<>();
while (in.hasNext()) {
final double value = Double.parseDouble(in.next());
if (value >= 0.1) {
list.add(value);
}
}
System.out.println(list);
}
and if you really want to remove items from the List I would use the iterator remove method:
for (Iterator<Double> iterator = arr.iterator(); iterator.hasNext(); ) {
Double next = iterator.next();
if (next < 0.1) {
iterator.remove();
}
}
Or even better wait until Java 8 is released (in a few hours) and use the new functional api to filter the collection which leaves the original collection untouched.
Upvotes: 0
Reputation: 3934
If you use generics, your IDE will complain, and you could see then the problem very easily. At the time you try to parse the elements from String to Double, they are actually seen by the compiler as Object (even if they are actually Strings), you miss a cast here.
Here is a first fix :
public static void main(String[] args) throws IOException {
List<Double> arr = new ArrayList<Double>();
File f = new File("C:\\java\\marchcalllast.csv");
Scanner in = new Scanner(f).useDelimiter(",");
while (in.hasNext()) {
arr.add(Double.valueOf(in.next()));
}
for (Double item : arr) {
if (item < 0.1) {
arr.remove(item); // This is not allowed here, you are iterating on arr
}
}
System.out.println(arr);
}
Now, there is an other bug : you can not remove an element from a collection while iterating on it. To fix that, you can for example, use a second temporary collection :
public static void main(String[] args) throws IOException {
List<Double> arr = new ArrayList<Double>();
File f = new File("C:\\java\\marchcalllast.csv");
Scanner in = new Scanner(f).useDelimiter(",");
while (in.hasNext()) {
arr.add(Double.valueOf(in.next()));
}
List<Double> toRemove = new ArrayList<Double>();
for (Double item : arr) {
if (item < 0.1) {
toRemove.add(item);
}
}
arr.removeAll(toRemove);
System.out.println(arr);
}
Upvotes: 1
Reputation: 8311
Your ArrayList doesn't specify what type it contains. So it's treated as though it just contains "Objects". So, even though you are adding Strings to it, when you do "get", it still returns you Objects. But Double.valueOf wants Strings to parse, not Objects. So a cast would work:
Double item = Double.valueOf((String) arr.get(i));
However, you can use generics to specify what type of item your ArrayList will hold:
List<String> arr=new ArrayList<String>();
Now, you won't need that cast because the "get" will return you Strings.
Upvotes: 0
Reputation: 3887
You can roll the second loop into the CSV parsing stage. If you know the input should be numbers, you can ignore the non-number inputs using exception handling.
Here's an example:
public static void main(String[] args) throws InvalidFormatException, IOException{
List arr=new ArrayList();
File f=new File("C:\\java\\marchcalllast.csv");
Scanner in=new Scanner(f).useDelimiter(",");
while(in.hasNext()){
String nextToken = in.next();
try{
Double tokenAsNumber = Double.parseDouble(nextToken);
if(tokenAsNumber >= 0.1){
arr.add(tokenAsNumber);
}
else{
System.out.println("Ignoring value less than 0.1: "+tokenAsNumber);
}
}
catch(NumberFormatException nfe){
System.err.println(nextToken + " is not a number, ignoring");
}
}
System.out.println(arr);
}
Converting early is pretty good practice :)
Upvotes: 0
Reputation: 1
You do not need to get the value with .valueOf()
. You just need to write Double item = arr.get(i);
to get the value at this index and continue with the if statement.
Upvotes: 0