Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 比较树映射中的值_Java - Fatal编程技术网

Java 比较树映射中的值

Java 比较树映射中的值,java,Java,我在Map中存储了一些日志,其中字符串表示操作,日期表示操作执行的日期 Sat Jan 11 06:00:00 IST 2014=Read User Fri May 15 05:45:56 IST 2015=Update User Tue Nov 21 07:23:00 IST 2017=Create User Tue Nov 21 08:34:00 IST 2017=Delete User Thu Nov 23 11:34:00 IST 2017=Create User

我在
Map
中存储了一些日志,其中字符串表示操作,日期表示操作执行的日期

  Sat Jan 11 06:00:00 IST 2014=Read User
  Fri May 15 05:45:56 IST 2015=Update User
  Tue Nov 21 07:23:00 IST 2017=Create User  
  Tue Nov 21 08:34:00 IST 2017=Delete User
  Thu Nov 23 11:34:00 IST 2017=Create User
  Mon Jul 30 10:34:20 IST 2018=Delete User
我的要求是,对于日志,创建一个新的映射,其中操作将是旧的操作+旧映射中位于其下方的相同值的操作

示例输出:

Sat Jan 11 06:00:00 IST 2014=Read User
Fri May 15 05:45:56 IST 2015=Update User
Tue Nov 21 07:23:00 IST 2017=Create User  Create User [Thu Nov 23 11:34:00 
                                                                IST 2017 ]
Tue Nov 21 08:34:00 IST 2017=Delete User  Delete User [Mon Jul 30 10:34:20 
                                                                IST 2018 ]
Thu Nov 23 11:34:00 IST 2017=Create User
Mon Jul 30 10:34:20 IST 2018=Delete User
我的解决方案:

Map<Date, String> auditMap = new TreeMap<Date, String>();
Map<Date, String> auditMap2 = new TreeMap<Date, String>();

Collection<String> ls = auditMap.values();
Object[] arr = ls.toArray();
int count = 1;

for(Map.Entry<Date, String> d: auditMap.entrySet()) {               
    String da = d.getValue();

    for (int i = count ; i<arr.length ; i++) {
        if(d.getValue().equals(arr[i])) {
            da = da.concat("  ").concat((String) arr[i]).concat(" [" + auditMap.keySet().toArray()[i] +" ]");                       
        }
    }

    count++;
    auditMap2.put(d.getKey(), da);
}

for (Map.Entry<Date, String> d1: auditMap2.entrySet()) {
    System.out.println(d1);
}
Map auditMap=newtreemap();
Map auditMap2=newtreemap();
集合ls=auditMap.values();
对象[]arr=ls.toArray();
整数计数=1;
对于(Map.Entry d:auditMap.entrySet()){
字符串da=d.getValue();

对于(int i=count;i则解决方案是将包含
操作和数据的输入存储为
列表作为成员。然后将其分组为
操作
作为键,并使用groupingBy函数将时间
作为设定值。请参见以下算法是另一个带有
O(n²)的版本
更具可读性的复杂性:

Map<Date, String> auditMap = new TreeMap<>();
Map<Date, String> result = new TreeMap<>();

List<Map.Entry<Date, String>> entries = Lists.newArrayList(auditMap.entrySet());
for (int i = 0; i < entries.size(); i++) {
    Map.Entry<Date, String> entry = entries.get(i);

    // This SB will contain all next occurrences
    StringBuilder sb = new StringBuilder(entry.getValue());

    // Checks all the next occurrences in the iterator for equal values
    // To add them to the SB
    for (int j = i + 1; j < entries.size(); j++) {
        if (Objects.equals(entries.get(j).getValue(), entry.getValue())) {
            sb.append(" ").append(entry.getValue());
            sb.append(" [").append(entry.getKey()).append("]");
        }
    }

    // Builds the result map
    result.put(entry.getKey(), sb.toString());
}
Map auditMap=newtreemap();
映射结果=新树映射();
List entries=Lists.newArrayList(auditMap.entrySet());
对于(int i=0;i
复杂性分析: 原始地图上的循环统计n个项目

然后,嵌套循环计数(n-i+1)项,依次为:(n-1),(n-2),…,1项


总数是从1到n的总和,等于n*(n+1)/2。这意味着总复杂度是
O(n²)

线性方法

可实现的最小复杂性为
O(n)
,审计映射的大小为
n
,因为您需要至少遍历每个审计操作一次

您的算法基本上是二次的(
O(n^2)

如果需要更高的复杂性,则需要确保在
auditMap
的每个元素上迭代一次:

Map<Date, String> auditMap = new TreeMap<Date, String>();
Map<String, AggregatedAction> aggregatedActions = new HashMap<>();

// Traverse each action once.
for (Map.Entry<Date, String> e : auditMap.entrySet()) {
  Date date = e.getKey();
  String action = e.getValue();

  // If the number of types of actions is small, the lookup in the 
  // aggregatedActions map can be estimated to be O(1).
  AggregatedAction aggregated = aggregatedActions.get(action);
  if (aggregated == null) {
    aggregated = new AggregatedAction(date, action);
    aggregatedActions.put(action, aggregated);

  } else {
    aggregated.append(date);
  }
}

// If you want a copy of your original map,
// otherwise you could just update it in place.
Map<Date, String> auditMap2 = new LinkedHashMap<Date, String>(auditMap);

// O(b) where b is the number of types of actions.
for (AggregatedAction action : aggregatedActions.values()) {
  auditMap2.put(action.firstOccurence, action.concatenatedAction.toString());
}
复杂性分析

  • n
    审核图的大小
  • b
    aggregatedActions的大小

上述代码实现了
O(n+b)=O(n)
if
b提高性能的步骤很少:

注意,我假设您需要就地解决方案

1) 根据值对树映射进行排序。它将帮助您停止迭代(稍后的步骤您将了解)。O(n logn)

2) 创建一个临时变量,用于存储开始/最后处理的元素

3) 开始迭代并检查每个值。在这种情况下,内部循环将在那里给出下一个值,如果外部循环值匹配,则将其添加到上一个输入值中。在每次迭代时,内部循环值将从迭代器中删除它,因此它将从树映射中删除,并将成为同一操作的值的一部分

4) 现在完成后,您的地图将具有所有值作为输出


请注意,具有两个循环(外部和内部)的迭代器将花费O(n)次。因此,最糟糕的解决方案是使用O(n log n)。

在输出中,为什么有重复的“创建用户”和“删除相同”项。这是您要找的正确输出,还是您希望有特定操作(创建或删除等)的所有日期在同一个位置?输出是正确的。设想一下,我正在从地图上读取“创建用户”,然后我必须在下面查找其他“创建用户”。如果有,则添加两个操作。如果没有,则将原始值放入新地图中。请在计算下面和计算之后查看我的地图。是否要添加所有以下事件或JU不是第一个下一个吗?添加它下面的所有事件。但是没有测试它,请告诉我它是否有任何问题。while(iterator.hasNext())只需要对map中的第一个值进行一次迭代。它不会对其余的值进行迭代。但是,我喜欢你的想法。哦,这意味着
foreachrestain
会消耗其余的值…哦,是的。当然。我当时更换了迭代器。这是怎么回事?看起来仍然是o(nlog(n)),我在考虑o(n)解决方案。我喜欢你的想法,但主要问题是上面的代码搜索事件并删除剩余的事件。请检查我的输出以获取参考,你的代码删除了最后两行。@amansaraf你确定吗?我想你保留了所有内容是因为复制:
auditMap2=new TreeMap(auditMap)
。通过将
auditMap
传递给
TreeMap
的构造函数,它将
auditMap
的所有元素复制到
auditMap2
中。哎呀,我错过了这一点,我没有运行你的代码,只是通过查看它来分析输出。是的,它将复制所有内容以及操作,这看起来不错。非常好的操作方式实现。我唯一担心的是附加
字符串的成本。如果成本太高,您可以用另一个结构(如果可能)来代替它,例如a(链接)列表。但我想你还是需要在某个时候把它合并成一个
字符串
。@amansaraf谢谢,从某种意义上说,这个问题是非常实际的,关于双迭代和更线性的方法的类似疑问可能很常见。关注“最优”这里的复杂性倾向于过早的优化,这弊大于利。这当然很有趣,但同时也带来了更多的冗长。一个结合了优化算法和优化算法的解决方案
public static final class AggregatedAction {
  private final StringBuilder concatenatedAction = new StringBuilder();
  private final String action;
  private final Date firstOccurence;

  public AggregatedAction(Date firstOccurence, String action) {
    this.firstOccurence = firstOccurence;
    this.action = action;
    concatenatedAction.append(action);
  }

  public void append(Date nextOccurence) {
    concatenatedAction.append(" ").append(action).append(" [").append(nextOccurence).append(" ]");
  }
}