如何使用Java 8流方法(例如,对于数组Stream<T>
,以惯用方式枚举T
将每个T[] values
实例映射到唯一整数,从而创建Map<T,Integer>
其中Map.get(values[i]) == i
评估为true
)?
目前,我定义了一个匿名类,该类增加int
字段以便与Collectors.toMap(..)
方法一起使用:
private static <T> Map<T, Integer> createIdMap(final Stream<T> values) {
return values.collect(Collectors.toMap(Function.identity(), new Function<T, Integer>() {
private int nextId = 0;
@Override
public Integer apply(final T t) {
return nextId++;
}
}));
}
但是,使用Java 8流API是否没有更简洁/更优雅的方法? - 如果可以安全地并行化,则可获得奖励积分。
答案 0 :(得分:5)
如果存在重复元素,您的方法将失败。
除此之外,您的任务需要可变状态,因此可以使用Mutable reduction来解决。当我们填充地图时,我们可以简单地使用地图的大小来获取未使用的ID。
更棘手的部分是合并操作。以下操作只是重复右图的分配,它将处理潜在的重复。
distinct()
如果我们依赖于唯一元素,或者插入明确的private static <T> Map<T, Integer> createIdMap(Stream<T> values) {
return values.distinct().collect(HashMap::new, (m,t) -> m.put(t,m.size()),
(m1,m2) -> { int leftSize=m1.size();
if(leftSize==0) m1.putAll(m2);
else m2.forEach((t,id) -> m1.put(t, leftSize+id));
});
}
,我们可以使用
var apiUrl : String
var alamoFireManager:Manager!
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
init(apiUrl : String){
self.apiUrl = apiUrl
configuration.timeoutIntervalForRequest = 30.0
alamoFireManager = Alamofire.Manager(configuration: configuration)
}
print(apiUrl)
alamoFireManager.request(.GET, apiUrl, encoding: .JSON).validate(contentType: ["application/json"]) .responseJSON { response in
print(response.result.value)
switch response.result{
case .Success:
if let value = response.result.value{
let json = JSON(value)
print (json)
callback.onResponse(value) // this is where my value is sent
}
case .Failure(let error):
print(error.localizedDescription)
}
}
答案 1 :(得分:4)
我会这样做:
private static <T> Map<T, Integer> createIdMap2(final Stream<T> values) {
List<T> list = values.collect(Collectors.toList());
return IntStream.range(0, list.size()).boxed()
.collect(Collectors.toMap(list::get, Function.identity()));
}
为了起因或平行,可将其更改为
return IntStream.range(0, list.size()).parallel().boxed().
(...)
答案 2 :(得分:0)
比较在Andremoniy提供的解决方案中首先将输入流转换为List。我宁愿以不同的方式做到这一点,因为我们不知道“toList()”和“list.get(i)”的成本,并且没有必要创建一个额外的List,它可能小或者更大
private static <T> Map<T, Integer> createIdMap2(final Stream<T> values) {
final MutableInt idx = MutableInt.of(0); // Or: final AtomicInteger idx = new AtomicInteger(0);
return values.collect(Collectors.toMap(Function.identity(), e -> idx.getAndIncrement()));
}
无论问题如何,我认为将流作为参数传递给方法是一种糟糕的设计。