2

Suppose I have some file having some data in comma separated format as below

TIMESTAMP,COUNTRYCODE,RESPONSETIME,FLAG

1544190995,US,500,Y
1723922044,GB,370,N
1711557214,US,750,Y

My requirement is, I want to read this file and filter data based on columns(TIMESTAMP and RESPONSETIME) and check whether the data is numeric or not.

I have tried as below, but it did not work. Can some one assist me on the same ?

BufferedReader br = new BufferedReader(new FileReader(file));

rows = br.lines().map(line -> Arrays.asList(line.split(DELIMITER))).filter(a -> a.equals("TIMESTAMP")).collect(Collectors.toList());
5
  • what did you mean by it did not work? Commented May 11, 2018 at 19:22
  • did you try to makes it without lambda, because I see that the map return ArrayList then you use .filter(a -> a.equals("TIMESTAMP")) which is not logic ArrayList is not a String no? Commented May 11, 2018 at 19:30
  • I mean, it did not give me the expected outcome. Expected Outcome: It should return the boolean value ->'true' -> If both the fields are numeric (TIMESTAMP and RESPONSETIME) ->'false' -> Either one the fields are non numeric (TIMESTAMP and RESPONSETIME)) Commented May 11, 2018 at 19:37
  • Thanks. Cant we achieve with lamda. ? Commented May 11, 2018 at 19:38
  • No you can, can you please show us the result of br.lines().forEach(System.out::println) Commented May 11, 2018 at 19:40

4 Answers 4

2

Currently, after the map operation, you have a Stream<List<String>> and you're trying to compare that with a String, hence will never yield the expected outcome.

Now, to the solution; from what I can gather it seems that you want to retain the entire line if the TIMESTAMP and RESPONSETIME are valid integers.

One way to go about this is:

 List<String> rows = br.lines()
            .skip(1) // skip headers
            .map(s -> new AbstractMap.SimpleEntry<>(s,s.split(DILIMETER)))
            .filter(a -> isInteger(a.getValue()[0]) && isInteger(a.getValue()[2]))
            .map(AbstractMap.SimpleEntry::getKey)
            .collect(Collectors.toList());

and the isInteger function being defined as follows:

public static boolean isInteger(String input)
{
      if(input == null || input.trim().isEmpty()) return false;
      for (char c : input.toCharArray())
          if (!Character.isDigit(c)) return false;
      return true;
}

Another solution being is if you want to retrieve a List<String[]> where each array represents the individual data of each line then you can do:

List<String[]> rows = br.lines()
                .skip(1) // skip headers
                .map(s -> s.split(DILIMETER))
                .filter(a -> isInteger(a[0]) && isInteger(a[2]))
                .collect(Collectors.toList());

Note, if the file being read only contains the data with no headers then there is no need to perform the skip operation.

Sign up to request clarification or add additional context in comments.

Comments

1

the problem is you will just get a list full of "TIMESTAMP" which isn't useful. if the file format is always the same, meaning the order and number of headers, you can just skip the first line, then read each of the lines with the data and access just the columns with the data you want to validate. and it may be better to use a for or while loop so you can terminate early.

boolean allNumericData = true;
do{
   String[] row = br.nextLine().split(DELIMITER)
   if(!isNumeric(row[0])||!isNumeric(row[2])){
       allNumericData = false;
   }
}while(allNumericData ||br.nextRow = null)

if the headers can be different then open the file read the first row to determine the index of the data required to validate, and do the same as above but with the found index. also this is pseudo code. you will need to do the validation and handling of fetching and null checking the next row

Comments

1

Presently this is what you doing :

  1. read all lines that give : List<String>
  2. You split it so that give you String[] and you convert it to List<String> (that is correct) but you are in a map so the result of the map is Stream<List<String>>
  3. You filter and a is a List. You try to compare a List and a String. Bip bip bop bop, problem!

Like @YCF_L said, try it without lambda..

2 Comments

the result of the map operation is Stream<List<String>> not List<List<String>>.
you are right! just realise it but you are too fast for me ;)
0

You can as well use flatMap and later on filter only string containing digits:

List<String> timeAndResponse = br.lines()
        .flatMap(s -> Arrays.stream(s.split(",")))
        .filter(s -> s.chars().allMatch(Character::isDigit))
        .collect(Collectors.toList());

In this case you are working with streams only:

.flatMap(s -> Arrays.stream(s.split(","))) we take an individual line from the file, split it by , - take a stream from an intermediate array and finally call flatMap. This will give us Stream<String> where String is and individual string from original line 1544190995,US,500,Y. After this point let's just leave only numeric string using filter. Finally let's collect everything to a List, which will contain the following values:

[1544190995, 500, 1723922044, 370, 1711557214, 750]

I hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.