实际上这是LeetCode#56,我使用TreeMap来计算结果。
代码是:
public List<Interval> merge(List<Interval> intervals) {
Map<Integer, Integer> tMap = intervals.stream().collect(Collectors.toMap(i -> i.start, i -> i.end, (i, j) -> i > j ? i : j));
Map<Integer, Integer> map = new TreeMap<Integer, Integer> (tMap);
List<Interval> res = new ArrayList<Interval>();
int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, tmpLeft = -1, tmpRight = -1;
Set<Map.Entry<Integer, Integer>> set = map.entrySet();
for (Map.Entry<Integer, Integer> entry : set)
{
if (Integer.MAX_VALUE == left && Integer.MAX_VALUE == right)
{
left = entry.getKey();
right = entry.getValue();
}
else
{
tmpLeft = entry.getKey();
tmpRight = entry.getValue();
if(right < tmpLeft)
{
res.add(new Interval(left, right));
left = tmpLeft;
}
right = right > tmpRight ? right : tmpRight;
}
}
if (Integer.MAX_VALUE != left && Integer.MAX_VALUE != right)
res.add(new Interval(left, right));
return res;
}
虽然它有效,但我想知道是否有办法在流中做到这一点。
可以通过流直接生成TreeMap Map<Integer, Integer> map = new TreeMap<Integer, Integer> (tMap);
吗?
当我有Set<Map.Entry<Integer, Integer>> set
及以下for循环时,是否有某种方法可以在流中执行此操作?
答案 0 :(得分:1)
1-使用toMap
收集器方法,该方法也接受Supplier<M>
:
Map<Integer, Integer> tMap = intervals.stream().collect(Collectors.toMap(i -> i.start, i -> i.end, (i, j) -> i > j ? i : j), () -> new TreeMap<Integer, Integer>());
2-您可以替换:
Set<Map.Entry<Integer, Integer>> set = map.entrySet();
for (Map.Entry<Integer, Integer> entry : set)
{ ...
使用:
map.entrySet().stream().forEach(entry -> { ...
但我认为这不值得。
答案 1 :(得分:1)
您可以将TreeMap
创建简化为
Map<Integer, Integer> map = intervals.stream()
.collect(Collectors.toMap(i -> i.start, i -> i.end, Math::max, TreeMap::new));
但实际上,TreeMap
只是用于获取按起点排序的区间数据的kludge。虽然如果您确实需要排序存储,TreeMap
就足够了,但对于一次性排序来说,它不是最有效的解决方案。
您可以使用:
intervals = intervals.stream()
.sorted(Comparator.comparingInt(i -> i.start))
.collect(Collectors.toList());
int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, tmpLeft = -1, tmpRight = -1;
// proceed with your loop as before,
// using i.start and i.end instead of entry.getKey() and entry.getValue()
for(Interval i: intervals)
{
…
但是,在这里使用Collection API可能更有效:
intervals = new ArrayList<>(intervals);
intervals.sort(Comparator.comparingInt(i -> i.start));
int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, tmpLeft = -1, tmpRight = -1;
// proceed with your loop as before,
// using i.start and i.end instead of entry.getKey() and entry.getValue()
for(Interval i: intervals)
{
…
在这两种情况下,都会创建一个新列表,假设您不想修改参数列表并独立于该列表的实现细节。
循环的逻辑可以表示为流操作,但它不会像循环那样简单。你需要一个自定义收集器,它带有你现在在循环中所做的几乎相同的操作,加上一个合并函数,它对两个列表做了类似的操作,以支持并行操作。