[英]Stream a list of n-integers from a file to create n object array
Assume each T object can be instantiated as 假设每个T对象都可以实例化为
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: 因此,要在由空格分隔的文件中从整数创建T []数组,请执行以下操作:
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? 1.上述方法在时间和空间使用方面是否有效?
2.Is there any other way? 2.还有其他办法吗? 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 . 另请注意,现在我们使用称为NIO的 Javas新I / O API读取文件。 One big advantage is that it offers
Stream
methods. 一个很大的优点是它提供了
Stream
方法。 For example the Files#lines
method that returns a stream over all lines of the file, perfectly suited for your approach. 例如,
Files#lines
方法在文件的所有行上返回一个流,非常适合您的方法。
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. 与原始方法的主要区别在于我们可以使用
mapToObj(T::new)
(或者只是map
如果它是常规流而不是IntStream
)将IntStream
转换为Stream<T>
, mapToObj(T::new)
元素传递给构造函数。 After that we collect Stream<T>
into an array by using toArray(T[]::new)
. 之后,我们使用
toArray(T[]::new)
将Stream<T>
收集到一个数组中。
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 编辑:注意到你使用的是不同的分隔符
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.