CodeQL 文档

密钥集迭代器的低效使用

ID: java/inefficient-key-set-iterator
Kind: problem
Security severity: 
Severity: recommendation
Precision: high
Tags:
   - efficiency
   - maintainability
Query suites:
   - java-security-and-quality.qls

点击查看 CodeQL 存储库中的查询

Java 的集合框架提供了多种遍历映射内容的方法。您可以检索键集、值集合或“条目”集(实际上是键/值对)。

迭代器的选择会影响性能。例如,如果循环体对每个检索到的键执行映射查找,则迭代映射的键集被认为是不良做法。

建议

评估循环体的要求。如果它除了在映射中查找之外实际上不需要键,则迭代映射的值(通过调用 values 获得)即可。如果循环确实需要映射中每个映射的键和值,则迭代条目集(通过调用 entrySet 获得)并从每个条目中检索键和值。这每次都会节省更昂贵的映射查找。

示例

在以下示例中,方法 findId 的第一个版本使用键集迭代映射 people。这是低效的,因为循环体需要访问每个键的值。相比之下,第二个版本使用条目集迭代映射,因为循环体需要每个映射的键和值。

// AVOID: Iterate the map using the key set.
class AddressBook {
	private Map<String, Person> people = ...;
	public String findId(String first, String last) {
		for (String id : people.keySet()) {
			Person p = people.get(id);
			if (first.equals(p.firstName()) && last.equals(p.lastName()))
				return id;
		}
		return null;
	}
}

// GOOD: Iterate the map using the entry set.
class AddressBook {
	private Map<String, Person> people = ...;
	public String findId(String first, String last) {
		for (Entry<String, Person> entry: people.entrySet()) {
			Person p = entry.getValue();
			if (first.equals(p.firstName()) && last.equals(p.lastName()))
				return entry.getKey();
		}
		return null;
	}
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私