I see nothing wrong with the performance of your code. That is, I dispute the claim that your program has anything wrong with it.
Reading data from files, or across the network, is several orders of magnitude slower than manipulating data in memory. The performance of code that mixes I/O with some manipulation of data in memory is therefore typically dominated by the time taken for the I/O. Tweaks to the manipulation of data in memory are rarely worthwhile. If I/O operations happen in parallel with data manipulation (which will be the case if the O/S does some read-ahead), the data manipulation can be almost free: making the data manipulation faster will not decrease the time taken because any decreases in the CPU time for the data manipulation will be precisely offset by an increase in the amount of time that the program blocks while awaiting input.
Programs that do I/O and need good performance must decrease the amount of time they spend blocked  awaiting I/O. They should operate in a manner that enables them to take advantage of the optimizations that the hardware and operating system provide to reduce the amount of blocking.
Importantly, at the low level, disks and networks do not operate on small numbers of bytes for each operation. They use larger units of packets or blocks. Interacting with the operating system to read fewer bytes than are stored in one disk block is wasteful. Programs avoid doing that by buffering their I/O, so the program itself changes a sequence of many small I/O operations into fewer but larger operations. You are using a BufferedReader, so you are already doing that.
The operating system is likely to do some read-ahead: if you ask for bytes in a block at the start of a file it will guess that you are probably going to read the file sequentially,  so it would be worthwhile for it to also fetch some of the subsequent blocks of the file, in anticipation of your program also needing those. Reading files sequentially gives better performance. You are already doing that.