有人可以解释一个选择另一个的主要好处以及该选择带来的不利因素吗?
你怎么能收缩LinkedHashMap?我重写了removeEldestEntry方法,但只在插入新值时才调用此方法一次.所以没有改变使地图变小的方式.
该LinkedHashMap只给我一个正常的Iterator,并没有任何removeLast或listIterator方法,那么如何找到最后,说1000,条目并删除它们?
我能想到的唯一方法是迭代整个事情.但这可能需要很长时间......
每次我只想删除少量元素时创建一个新地图也会破坏内存.
Iterator当方法maxSize中的减少时,可能会删除它的第一个值然后重新插入它们removeEldestEntry.然后重新插入将踢出最旧的值.这是非常难看的代码......有什么更好的想法吗?
编辑:Sry迭代顺序是最年轻的.这很容易
LinkedHashMap说明"它维护着一个贯穿其所有条目的双向链表",所以我想知道如何输入最后一个条目或密钥?我可以自信地转发.values()以LinkedList获得那个双重链接列表并使用.getLast()它吗?或者它是其他Java集合的实例?
java.util如果可能,我想坚持下去.
调用put或get方法会导致访问相应的条目(假设它在调用完成后存在).putAll方法为指定映射中的每个映射生成一个条目访问,按照指定映射的条目集迭代器提供键 - 值映射的顺序.没有其他方法可以生成入口访问.
为什么新的Map方法不会在LinkedHashMap上生成入口访问?特别是getOrDefault().这是否违反了最不惊讶的原则?
@PeterLawrey从源代码中可以清楚地看到:
getOrDefault被覆盖HashMap:
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
}
Run Code Online (Sandbox Code Playgroud)
LinkedHashMapHashMap仅扩展和覆盖get():
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
// generating entry access -- comment by me
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
Run Code Online (Sandbox Code Playgroud)
因此,不会生成入口访问getOrDefault().
LinkedHashMap.java使用了一个字段:
final boolean accessOrder;
Run Code Online (Sandbox Code Playgroud)
LinkedHashMap的构造函数是:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
Run Code Online (Sandbox Code Playgroud)
我想知道accessOrder字段的用途.请举例说明accessOrder是'true和'false'.有没有其他方法来更新已创建对象的accessOrder字段?
我正在为注册屏幕创建一个非常简单的表单验证实用程序,并且我遇到了一些意外的行为LinkedHashMap和从它创建的流entrySet.
我将验证结果存储在a中LinkedHashMap,具有以下语句顺序:
Map<ValidationResult.SignUpField, Boolean> fieldStatuses = new LinkedHashMap<>();
fieldStatuses.put(EMAIL, isValidEmail(emailAddress));
fieldStatuses.put(USERNAME, isValidUsername(username));
fieldStatuses.put(BIRTHDAY, isValidBirthday(birthday));
fieldStatuses.put(PASSWORD, isValidPassword(password));
fieldStatuses.put(CONFIRM_PASSWORD, password.equals(confirmedPassword));
List<ValidationEntry> invalidFields = aggregateInvalidFields(fieldStatuses);
Run Code Online (Sandbox Code Playgroud)
除了"确认密码"之外,一个特定的迭代产生上述所有字段无效.在条目集上使用简单的for循环并省略有效结果,无效结果按以下顺序显示:
然后我尝试使用Android上可用的Stream API子集(目标版本25,最小值为19,因此缺少Collectors.toMap()):
private static List<ValidationEntry> aggregateInvalidFields(Map<ValidationResult.SignUpField, Boolean> fields) {
List<ValidationEntry> invalidFields = new ArrayList<>();
fields.entrySet()
.stream()
.filter(entry -> !entry.getValue())
.forEachOrdered(entry -> {
ValidationResult.SignUpField field = entry.getKey();
invalidFields.add(new ValidationEntry(field, lookUpErrorCode(field)));
});
return invalidFields;
}
Run Code Online (Sandbox Code Playgroud)
但该代码产生以下顺序:
这里究竟发生了什么,为什么流的结果不符合LinkedHashMap?的插入顺序?需要注意的是,如果我换出forEachOrdered用forEach,它仍然没有插入排序.
我很难理解这一点.
谷歌搜索,我发现
"HashMap迭代器必须迭代所有桶,包括空桶"
和
"在LinkedHashMap中,所有条目都是双重链接的".
如果是这种情况,为什么唯一的HashMap必须迭代空桶,而不是LinkedHashMap,尽管两者都使用相同的桶概念实现?所有条目都是双重联系的,意思是" 所有的桶和元素都是双重联系的 ",或者只是" 元素是双重联系的 ".
请给我一个解释LinkedHashMap中双向链接桶实现的图表.
提前谢谢了.
某些测试用例在我的应用程序中失败,这取决于元素的插入顺序.它曾经在Java 7中运行良好但是这个问题在升级到Java 8之后就开始了.在搜索互联网时我在一篇文章中找到了这个 :
Java 8包含对HashSet/Map迭代顺序的一些可能的更改:
有些人可以建议我 - 我怎样才能以与插入顺序相同的顺序迭代Map中的对象,考虑到我仍然在我的开发环境中使用Java 1.8?
是的,当然HashMap从未保证可以按相同的顺序检索对象,但是它曾经在java 7中工作.
不LinkedHashMap工作,落实呢?
用户上传一个包含100万字的大文件.我解析文件并将文件的每一行放入LinkedHashMap<Integer, String>.
我需要通过密钥进行O(1)访问和删除.此外,我需要保留访问顺序,从任何位置迭代和排序.
内存消耗巨大.我启用了Java 8中出现String的重复数据删除功能,但事实证明它LinkedHashMap消耗了大部分内存.
我发现LinkedHashMap.Entry 消耗40个字节,但只有2个指针 - 一个用于下一个条目,一个用于上一个条目.我认为1指针应该是64位或32位.如果我将409,405,320(字节)除以6,823,422(条目数),我买入每个条目60个字节.
我想我不需要前面的指针,下一个指针应该足以保持顺序.为什么LinkedHashMap消耗这么多内存?如何减少内存消耗?
java ×10
linkedhashmap ×10
hashmap ×3
collections ×2
java-8 ×2
android ×1
caching ×1
iterator ×1
java-stream ×1
key ×1
map ×1
trove4j ×1