Map<String, List<myStruct>> map1 = ...;
Map<String, List<myStruct>> map2 = ...;
myStruct有2个字段:时间戳和数字。
我需要使用map1和map2中的键创建一个新的map3。对于每个键,每次map1和map2的时间戳匹配时,我都需要在myStrcts列表中添加一个新条目。该数字应该等于map1的数字除以地图2的数字。
例如,如果每个人都有1个条目:
Map<String, List<myStruct>> map1 = < "Cat" , < <1pm, 10> <2pm, 6>, <3pm, 8>>;
Map<String, List<myStruct>> map2 = < "Cat" , < <1pm, 5> <2pm, 2>, <3pm, 1>>;
然后
Map<String, List<myStruct>> map3 = < "Cat" , < <1pm, 2> <2pm, 3>, <3pm, 8>>;
因为下午1点:10/5 = 2,下午2点:6/2 = 3,下午3点:8/1 = 8.
我曾尝试过使用lambda函数,但我无法提出任何好的和高效的东西。
我现在正在做的是迭代map1中的每个条目,然后遍历myStructs的每个时间戳 - 将它与map2中的时间戳进行比较,如果时间戳相等,则将结果添加到map 3。我试图找出一个更有效的解决方案。
答案 0 :(得分:1)
您可以遍历map1
的条目,然后通过流式传输地图的值来进行除法。
检查以下代码
tmp
是生成的List<myStruct>
tmp = e.getValue()
.stream()
.map(struct -> new myStruct(struct.time, map2.get(e.getKey())
.stream()
.filter(x -> x.time.equals(struct.time))
.mapToInt(x -> struct.number / x.number)
.findFirst().getAsInt()))
.collect(Collectors.toList());
public static void main(String[] args) {
Map<String, List<myStruct>> map1 = new HashMap<>();
Map<String, List<myStruct>> map2 = new HashMap<>();
myStruct one = new myStruct("1pm", 10);
myStruct two = new myStruct("1pm", 5);
myStruct thr = new myStruct("2pm", 6);
myStruct fou = new myStruct("2pm", 2);
myStruct fiv = new myStruct("3pm", 8);
myStruct six = new myStruct("3pm", 1);
map1.put("Cat", Arrays.asList(one, thr, fiv));
map2.put("Cat", Arrays.asList(two, fou, six));
Map<String, List<myStruct>> map3 = new HashMap<>(map1);
List<myStruct> tmp;
for (Map.Entry<String, List<myStruct>> e : map1.entrySet()) {
tmp = e.getValue()
.stream()
.map(struct -> new myStruct(struct.time, map2.get(e.getKey())
.stream()
.filter(x -> x.time.equals(struct.time))
.mapToInt(x -> struct.number / x.number)
.findFirst().getAsInt()))
.collect(Collectors.toList());
map3.put(e.getKey(), tmp);
}
System.out.println(map3); // {Cat=[<1pm, 2>, <2pm, 3>, <3pm, 8>]}
}
答案 1 :(得分:0)
您可以这样做:
这是我的结构类,时间戳为字符串字段(不知道实际示例中使用的数据类型,这仅供参考)
public class Mystruct
{
private String timeStamp;
private int number;
public Mystruct(String timeStamp,int number)
{
this.timeStamp=timeStamp;
this.number=number;
}
public Mystruct() {
// TODO Auto-generated constructor stub
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public String toString() {
return "Mystruct [timeStamp=" + timeStamp + ", number=" + number + "]";
}
}
测试课程:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map<String, List<Mystruct>> map1 = new HashMap<String, List<Mystruct>>();
Map<String, List<Mystruct>> map2 = new HashMap<String, List<Mystruct>>();
List<Mystruct> list1 = new ArrayList<Mystruct>();
List<Mystruct> list2 = new ArrayList<Mystruct>();
Mystruct struct1 = new Mystruct("1PM", 10);
Mystruct struct2 = new Mystruct("2PM", 6);
Mystruct struct3 = new Mystruct("3PM", 8);
list1.add(struct1);
list1.add(struct2);
list1.add(struct3);
Mystruct struct4 = new Mystruct("1PM", 5);
Mystruct struct5 = new Mystruct("2PM", 2);
Mystruct struct6 = new Mystruct("3PM", 1);
list2.add(struct4);
list2.add(struct5);
list2.add(struct6);
map1.put("Cat", list1);
map2.put("Cat", list2);
List<Mystruct> list3 = null;
List<Mystruct> list4 = null;
Map<String, List<Mystruct>> map3 = new HashMap<String, List<Mystruct>>();
for (String key : map1.keySet())
{
if(map2.get(key)!=null)
{
list3=map1.get(key);
list4=map2.get(key);
List<Mystruct> structList = new ArrayList<Mystruct>();
for(Mystruct outerStruct:list3)
{
for(Mystruct innerStruct:list4)
{
if(outerStruct.getTimeStamp().equals(innerStruct.getTimeStamp()))
{
Mystruct structToStore=new Mystruct();
structToStore.setTimeStamp(outerStruct.getTimeStamp());
structToStore.setNumber(outerStruct.getNumber()/innerStruct.getNumber());
structList.add(structToStore);
}
}
}
map3.put(key, structList);
}
}
System.out.println(map3.toString());
}
}
输出:
{Cat = [Mystruct [timeStamp = 1PM,number = 2],Mystruct [timeStamp = 2PM, number = 3],Mystruct [timeStamp = 3PM,number = 8]]}
答案 2 :(得分:0)
这里有两个嵌套操作,合并地图并合并包含的列表。首先,我认为尝试在一个代码块中表达整个操作将变得非常难以理解。其次,合并这些List<myStruct>
非常昂贵,特别是如果它们往往很大。因此,应首先将其中一个列表转换为Map<String,Integer>
(假设String
为时间戳值的类型),从而实现高效查找。在该地图上进行定位,将具有这样的地图的其他列表合并到结果列表可以表示为
static List<myStruct> combine(List<myStruct> list, Map<String,Integer> map) {
return list.stream()
.map(a -> {
Integer b=map.get(a.getTimeStamp());
return b==null? null: new myStruct(a.getTimeStamp(), a.getNumber()/b);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
此实现关注其他地图中不存在的时间戳。如果总是有相应的条目,则该方法可以简化为
static List<myStruct> combineSimplified(List<myStruct> list, Map<String,Integer> map) {
return list.stream()
.map(a -> new myStruct(a.getTimeStamp(), map.get(a.getTimeStamp())/a.getNumber()))
.collect(Collectors.toList());
}
使用列表组合方法,地图处理变得如
一样简单// preparation step
Map<String, Map<String,Integer>> prep=map1.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream()
.collect(Collectors.toMap(myStruct::getTimeStamp, myStruct::getNumber))));
// final processing
Map<String, List<myStruct>> result = map2.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> combine(e.getValue(), prep.get(e.getKey()))));
当然,您可以将列表组合方法内联到lambda表达式中,但我不推荐它。可读性会受到很大影响。