我有很多日志文件,我想在java中处理它们,但我想先对它们进行排序,以便我可以获得更多人类可读的结果。
我的日志类:
public class Log{
//only relevant fields here
private String countryCode;
private AccessType accessType;
...etc..
}
AccessType是Enum,其值为WEB,API,OTHER。
我想用countryCode和accessType对Log对象进行分组,这样最终产品就是日志列表。
我得到了这个工作,可以通过countryCode将日志分组到日志列表中,如下所示:
public List<Log> groupByCountryCode(String countryCode) {
Map<String, List<Log>> map = new HashMap<String, List<Log>>();
for (Log log : logList) {
String key = log.getCountryCode();
if (map.get(key) == null) {
map.put(key, new ArrayList<Log>());
}
map.get(key).add(log);
}
List<Log> sortedByCountryCodeLogList = map.get(countryCode);
return sortedByCountryCodeLogList;
}
来自@Kaleb Brasee的例子:
这是我现在已经尝试了一段时间了,现在真的卡住了..
public List<Log> groupByCountryCode(String countryCode) {
Map<String, Map<AccessType, List<Log>>> map = new HashMap<String, Map<AccessType, List<Log>>>();
AccessType mapKey = null;
List<Log> innerList = null;
Map<AccessType, List<Log>> innerMap = null;
// inner sort
for (Log log : logList) {
String key = log.getCountryCode();
if (map.get(key) == null) {
map.put(key, new HashMap<AccessType, List<Log>>());
innerMap = new HashMap<AccessType, List<Log>>();
}
AccessType innerMapKey = log.getAccessType();
mapKey = innerMapKey;
if (innerMap.get(innerMapKey) == null) {
innerMap.put(innerMapKey, new ArrayList<Log>());
innerList = new ArrayList<Log>();
}
innerList.add(log);
innerMap.put(innerMapKey, innerList);
map.put(key, innerMap);
map.get(key).get(log.getAccessType()).add(log);
}
List<Log> sortedByCountryCodeLogList = map.get(countryCode).get(mapKey);
return sortedByCountryCodeLogList;
}
我不确定我知道自己在做什么
答案 0 :(得分:4)
你的问题令人困惑。您想要对列表进行排序,但是您要创建许多新列表,然后丢弃除其中一个之外的所有列表?
这是一种对列表进行排序的方法。请注意Collections.sort()
使用稳定排序。 (这意味着将保留一组国家/地区代码和访问类型中的项目的原始顺序。)
class MyComparator implements Comparator<Log> {
public int compare(Log a, Log b) {
if (a.getCountryCode().equals(b.getCountryCode()) {
/* Country code is the same; compare by access type. */
return a.getAccessType().ordinal() - b.getAccessType().ordinal();
} else
return a.getCountryCode().compareTo(b.getCountryCode());
}
}
Collections.sort(logList, new MyComparator());
如果你真的想要做你的代码当前正在做的事情,至少跳过创建不必要的列表:
public List<Log> getCountryAndAccess(String cc, AccessType access) {
List<Log> sublist = new ArrayList<Log>();
for (Log log : logList)
if (cc.equals(log.getCountryCode()) && (log.getAccessType() == access))
sublist.add(log);
return sublist;
}
答案 1 :(得分:1)
如果您能够使用它,Google的Guava库中有一个Ordering类可能有助于简化操作。这样的事情可能有用:
Ordering<Log> byCountryCode = new Ordering<Log>() {
@Override
public int compare(Log left, Log right) {
return left.getCountryCode().compareTo(right.getCountryCode());
}
};
Ordering<Log> byAccessType = new Ordering<Log>() {
@Override
public int compare(Log left, Log right) {
return left.getAccessType().compareTo(right.getAccessType());
}
};
Collections.sort(logList, byCountryCode.compound(byAccessType));
答案 2 :(得分:0)
您应首先创建新的内部地图,然后将其添加到外部地图:
if (map.get(key) == null) {
innerMap = new HashMap<AccessType, List<Log>>();
map.put(key, innerMap);
}
和list元素类似。这样可以避免创建不必要的地图元素,然后再将其覆盖。
总的来说,最简单的方法是使用与第一种方法相同的逻辑,即如果地图中没有元素,插入它,然后从地图中获取它:
for (Log log : logList) {
String key = log.getCountryCode();
if (map.get(key) == null) {
map.put(key, new HashMap<AccessType, List<Log>>());
}
innerMap = map.get(key);
AccessType innerMapKey = log.getAccessType();
if (innerMap.get(innerMapKey) == null) {
innerMap.put(innerMapKey, new ArrayList<Log>());
}
innerMap.get(innerMapKey).add(log);
}
答案 3 :(得分:0)
首先,看起来你要在for循环中将每个日志条目添加两次,最后一行map.get(key).get(log.getAccessType()).add(log);
。鉴于上面的代码,我认为你可以不用它。
修好后,要返回List<Log>
,您可以执行以下操作:
List<Log> sortedByCountryCodeLogList = new ArrayList<Log>();
for (List<Log> nextLogs : map.get(countryCode).values()) {
sortedByCountryCodeLogList.addAll(nextLogs);
}
我认为上面的代码应该将其展平为一个列表,仍然按国家/地区代码和访问类型进行分组(不是按插入顺序排列,因为您使用的是HashMap
而不是LinkedHashMap
),我想想就是你想要的。