Assume each T object can be instantiated as
T tobj = new T(//int value);
So to create an array of T[ ] from integers in a file seperated by space I do the following:
BufferedReader br;
FileReader fr;
int[] arr;
try{
fr = new FileReader(fo); // assume "fo" file name
br = new BufferedReader(fr);
arr = Arrays.stream(br.readLine().split("\\s")).mapToInt(Integer::parseInt).toArray();
}catch(SomeException e){//something else}
T[] tobjarr = new T[arr.length];
for(int i=0; i<arr.length; ++i)){
tobjarr[i] = new T(arr[i]);
}
1.Is the above method efficient in terms of time and space usage?
2.Is there any other way? if so how does it compare to above method?
In general your approach is fine. However, you can do that with a single stream cascade. Compared to your original approach this saves you one iteration.
Also note that nowadays we read files using Javas new I/O API called NIO. One big advantage is that it offers Stream
methods. For example the Files#lines
method that returns a stream over all lines of the file, perfectly suited for your approach.
So all in all, here is the complete code:
String file = ...
Pattern separator = Pattern.compile("\\s");
try (Stream<String> lines = Files.lines(Paths.get(file))) {
T[] values = lines // Stream<String> lines
.flatMap(separator::splitAsStream) // Stream<String> words
.mapToInt(Integer::parseInt) // IntStream values
.mapToObj(T::new) // Stream<T> valuesAsT
.toArray(T[]::new);
} catch (IOException e) {
System.out.println("Something went wrong.");
}
Note that this code is slightly different to yours, as yours will only process one line and mine all lines. You may change that if you don't want it:
List<T[]> valuesPerLine = Files.lines(Paths.get(file)) // Stream<String> lines
.map(separator::splitAsStream) // Stream<Stream<String>> wordsPerLine
.map(lineStream -> {
return lineStream // Stream<String> words
.mapToInt(Integer::parseInt) // IntStream values
.mapToObj(T::new) // Stream<T> valuesAsT
.toArray(T[]::new);
}) // Stream<T[]> valuesPerLine
.collect(Collectors.toList());
The main difference to your original approach is that we can easily transform an IntStream
into a Stream<T>
by using mapToObj(T::new)
(or just map
if it's a regular stream and not IntStream
) which passes the elements to the constructor. After that we collect Stream<T>
into an array by using toArray(T[]::new)
.
T[] array = Arrays.stream(br.readLine().split("\\s"))
.map(s -> new T(Integer.parseInt(s)))
.toArray(T[]::new)
EDIT: noticed that you're using a different delimiter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With