Loading page…
Rust walkthroughs
Loading page…
The indexmap crate provides IndexMap and IndexSet — hash-based data structures that preserve insertion order. Unlike HashMap and HashSet from the standard library, IndexMap iterates in the order elements were inserted. It also supports indexing by position, efficient iteration, and all the usual map operations. This is useful when you need deterministic ordering, JSON-like data structures, or want to iterate in insertion order.
Key features:
IndexMap<K, V> — ordered hash map (preserves insertion order)IndexSet<T> — ordered hash set (preserves insertion order)HashMapswap_remove vs shift_remove — different removal semantics# Cargo.toml
[dependencies]
indexmap = "2"use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
// Insert in specific order
map.insert("apple", 3);
map.insert("banana", 2);
map.insert("cherry", 5);
// Iterates in insertion order
for (key, value) in &map {
println!("{}: {}", key, value);
}
// Output: apple: 3, banana: 2, cherry: 5
}use indexmap::IndexMap;
fn main() {
// Create empty map
let mut map: IndexMap<&str, i32> = IndexMap::new();
// With capacity
let mut map: IndexMap<&str, i32> = IndexMap::with_capacity(10);
println!("Capacity: {}", map.capacity());
// From iterator
let map: IndexMap<&str, i32> = [
("one", 1),
("two", 2),
("three", 3),
].into_iter().collect();
println!("Map: {:?}", map);
// From array
let map: IndexMap<_, _> = IndexMap::from([
("a", 1),
("b", 2),
("c", 3),
]);
println!("From array: {:?}", map);
// Builder pattern
let map = IndexMap::<&str, i32>::new()
.into_iter()
.collect::<IndexMap<_, _>>();
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
// Insert
map.insert("apple", 3);
map.insert("banana", 2);
map.insert("cherry", 5);
println!("Map: {:?}", map);
// Get by key
let apple = map.get("apple");
println!("Apple: {:?}", apple);
// Get mutable
if let Some(value) = map.get_mut("banana") {
*value += 10;
}
println!("After mutation: {:?}", map);
// Contains key
println!("Contains apple: {}", map.contains_key("apple"));
println!("Contains grape: {}", map.contains_key("grape"));
// Length
println!("Length: {}", map.len());
// Is empty
println!("Is empty: {}", map.is_empty());
// Entry API
map.entry("apple").and_modify(|v| *v += 1).or_insert(100);
println!("After entry (existing): {:?}", map.get("apple"));
map.entry("grape").or_insert(4);
println!("After entry (new): {:?}", map.get("grape"));
// Remove
let removed = map.remove("banana");
println!("Removed: {:?}", removed);
println!("After remove: {:?}", map);
// Clear
map.clear();
println!("After clear: {}", map.len());
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
// Insert in specific order
map.insert("first", 1);
map.insert("second", 2);
map.insert("third", 3);
map.insert("fourth", 4);
// Iterate in insertion order
println!("Iteration order:");
for (key, value) in &map {
println!(" {} = {}", key, value);
}
// Iterate keys only
println!("\nKeys:");
for key in map.keys() {
println!(" {}", key);
}
// Iterate values only
println!("\nValues:");
for value in map.values() {
println!(" {}", value);
}
// Mutable iteration
for value in map.values_mut() {
*value *= 10;
}
println!("\nAfter modification: {:?}", map);
// Into iteration (consumes map)
let map: IndexMap<_, _> = [("a", 1), ("b", 2)].into_iter().collect();
for (key, value) in map {
println!("Consumed: {} = {}", key, value);
}
}
// Comparison with HashMap
fn compare_with_hashmap() {
use std::collections::HashMap;
use indexmap::IndexMap;
let mut std_map = HashMap::new();
std_map.insert("c", 3);
std_map.insert("a", 1);
std_map.insert("b", 2);
let mut index_map = IndexMap::new();
index_map.insert("c", 3);
index_map.insert("a", 1);
index_map.insert("b", 2);
println!("HashMap order (undefined): ");
for (k, v) in &std_map {
println!(" {} = {}", k, v);
}
println!("IndexMap order (insertion): ");
for (k, v) in &index_map {
println!(" {} = {}", k, v);
}
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
map.insert("apple", 3);
map.insert("banana", 2);
map.insert("cherry", 5);
// Get index of a key
let idx = map.get_index_of("banana");
println!("Index of banana: {:?}", idx);
// Get key-value by index
let (key, value) = map.get_index(1).unwrap();
println!("Index 1: {} = {}", key, value);
// Get mutable by index
let (key, value) = map.get_index_mut(2).unwrap();
*value += 100;
println!("Modified index 2: {} = {}", key, value);
// Get key at index
let key = map.keys()[1];
println!("Key at index 1: {}", key);
// Get value at index (using Index)
let value = &map["apple"];
println!("Value for apple: {}", value);
// Indices for iteration
for (idx, (key, value)) in map.iter().enumerate() {
println!("Index {}: {} = {}", idx, key, value);
}
}
// First and last elements
fn first_last() {
use indexmap::IndexMap;
let mut map = IndexMap::new();
map.insert("first", 1);
map.insert("middle", 2);
map.insert("last", 3);
// First element
if let Some((key, value)) = map.first() {
println!("First: {} = {}", key, value);
}
// Last element
if let Some((key, value)) = map.last() {
println!("Last: {} = {}", key, value);
}
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
map.insert("apple", 1);
map.insert("banana", 2);
map.insert("cherry", 3);
map.insert("date", 4);
println!("Before: {:?}", map.keys().collect::<Vec<_>>());
// swap_remove - swaps with last, doesn't shift indices
// Fast O(1) but changes order
map.swap_remove("banana");
println!("After swap_remove: {:?}", map.keys().collect::<Vec<_>>());
// Re-add for demonstration
map.insert("banana", 2);
println!("\nBefore: {:?}", map.keys().collect::<Vec<_>>());
// shift_remove - shifts all elements after it
// Preserves order but O(n)
map.shift_remove("banana");
println!("After shift_remove: {:?}", map.keys().collect::<Vec<_>>());
// Remove by index
let mut map2 = IndexMap::new();
map2.insert("a", 1);
map2.insert("b", 2);
map2.insert("c", 3);
// swap_remove_index
let removed = map2.swap_remove_index(1);
println!("\nRemoved index 1: {:?}", removed);
println!("Remaining: {:?}", map2.keys().collect::<Vec<_>>());
// shift_remove_index
let mut map3 = IndexMap::new();
map3.insert("a", 1);
map3.insert("b", 2);
map3.insert("c", 3);
let removed = map3.shift_remove_index(1);
println!("\nRemoved index 1: {:?}", removed);
println!("Remaining: {:?}", map3.keys().collect::<Vec<_>>());
}
// Removal with indices
fn remove_with_index() {
use indexmap::IndexMap;
let mut map = IndexMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
// Remove and get index
let (idx, key, value) = map.swap_remove_full("b").unwrap();
println!("Removed at index {}: {} = {}", idx, key, value);
}use indexmap::IndexMap;
fn main() {
let mut map: IndexMap<&str, i32> = IndexMap::new();
// Basic entry operations
map.entry("apple").or_insert(3);
map.entry("banana").or_insert(2);
println!("After or_insert: {:?}", map);
// or_insert_with - lazy evaluation
map.entry("cherry").or_insert_with(|| {
println!("Computing cherry value");
5
});
map.entry("cherry").or_insert_with(|| {
println!("This won't print - cherry exists");
10
});
println!("After or_insert_with: {:?}", map);
// and_modify - modify existing value
map.entry("apple").and_modify(|v| *v *= 2);
map.entry("grape").and_modify(|v| *v *= 2).or_insert(1);
println!("After and_modify: {:?}", map);
// or_insert_with_key
map.entry("date").or_insert_with_key(|key| {
println!("Inserting key: {}", key);
key.len() as i32
});
println!("After or_insert_with_key: {:?}", map);
// or_default
map.entry("elderberry").or_default();
println!("After or_default: {:?}", map);
// Check if occupied or vacant
match map.entry("apple") {
indexmap::map::Entry::Occupied(entry) => {
println!("Apple is occupied with value: {}", entry.get());
}
indexmap::map::Entry::Vacant(entry) => {
println!("Apple is vacant");
}
}
}
// Entry with index
fn entry_with_index() {
use indexmap::IndexMap;
let mut map: IndexMap<&str, i32> = IndexMap::new();
// Get entry and its index
let entry = map.entry("apple");
let index = entry.index();
map.entry("apple").or_insert(1);
println!("Apple inserted at index: {}", index);
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
// insert returns old value if key exists
map.insert("apple", 3);
let old = map.insert("apple", 5);
println!("Old value: {:?}", old);
println!("New value: {:?}", map.get("apple"));
// insert_full returns (index, old_value)
let (idx, old) = map.insert_full("apple", 10);
println!("Index: {}, Old: {:?}", idx, old);
// Get mutable reference
if let Some(value) = map.get_mut("apple") {
*value += 1;
}
println!("After get_mut: {:?}", map.get("apple"));
// Update value in place
map.entry("apple").and_modify(|v| *v *= 2);
println!("After and_modify: {:?}", map.get("apple"));
// Retain - keep only matching entries
map.insert("banana", 2);
map.insert("cherry", 5);
map.insert("date", 8);
map.retain(|_key, &mut value| value > 3);
println!("After retain: {:?}", map);
// Append - add all from another map
let mut map2 = IndexMap::new();
map2.insert("elderberry", 4);
map2.insert("fig", 6);
map.extend(map2);
println!("After extend: {:?}", map.keys().collect::<Vec<_>>());
}
// Bulk updates
fn bulk_updates() {
use indexmap::IndexMap;
let mut map = IndexMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
// Update from iterator
let updates = vec![
("a", 10),
("d", 4), // New key
];
for (key, value) in updates {
map.insert(key, value);
}
println!("After updates: {:?}", map);
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
map.insert("cherry", 5);
map.insert("apple", 3);
map.insert("banana", 2);
map.insert("date", 8);
println!("Original order: {:?}", map.keys().collect::<Vec<_>>());
// Sort by key
map.sort_keys();
println!("Sorted by key: {:?}", map.keys().collect::<Vec<_>>());
// Sort by values (using sorted_by)
let mut map2 = IndexMap::new();
map2.insert("a", 3);
map2.insert("b", 1);
map2.insert("c", 2);
map2.sort_by(|_k1, v1, _k2, v2| v1.cmp(v2));
println!("Sorted by value: {:?}", map2.iter().collect::<Vec<_>>());
// Sort unstable (faster, may not preserve equal element order)
map2.sort_unstable_by(|_k1, v1, _k2, v2| v1.cmp(v2));
// Reverse
let mut map3 = IndexMap::new();
map3.insert("a", 1);
map3.insert("b", 2);
map3.insert("c", 3);
map3.reverse();
println!("Reversed: {:?}", map3.keys().collect::<Vec<_>>());
}
// Sorting with custom comparator
fn custom_sorting() {
use indexmap::IndexMap;
let mut map = IndexMap::new();
map.insert("apple", 10);
map.insert("banana", 5);
map.insert("cherry", 15);
map.insert("date", 3);
// Sort by value descending
map.sort_by(|_k1, v1, _k2, v2| v2.cmp(v1));
println!("Sorted by value (descending):");
for (key, value) in &map {
println!(" {} = {}", key, value);
}
// Sort by key length, then alphabetically
let mut map2 = IndexMap::new();
map2.insert("zz", 1);
map2.insert("a", 2);
map2.insert("bbb", 3);
map2.insert("ccc", 4);
map2.sort_by(|k1, _v1, k2, _v2| {
k1.len().cmp(&k2.len()).then(k1.cmp(k2))
});
println!("\nSorted by length then key:");
for (key, value) in &map2 {
println!(" {} = {}", key, value);
}
}use indexmap::IndexMap;
fn main() {
let mut map = IndexMap::new();
map.insert("apple", 1);
map.insert("banana", 2);
map.insert("cherry", 3);
map.insert("date", 4);
println!("Before swap: {:?}", map.keys().collect::<Vec<_>>());
// Swap two elements by index
map.swap_indices(0, 3);
println!("After swap 0 and 3: {:?}", map.keys().collect::<Vec<_>>());
// Move element to end
map.move_index(1, 3); // Move index 1 to position 3
println!("After move 1 to 3: {:?}", map.keys().collect::<Vec<_>>());
}
// Reordering elements
fn reordering() {
use indexmap::IndexMap;
let mut map = IndexMap::new();
map.insert("first", 1);
map.insert("second", 2);
map.insert("third", 3);
map.insert("fourth", 4);
// Move to front
if let Some(idx) = map.get_index_of("third") {
map.move_index(idx, 0);
}
println!("After moving third to front: {:?}", map.keys().collect::<Vec<_>>());
// Move to back
if let Some(idx) = map.get_index_of("first") {
map.move_index(idx, map.len() - 1);
}
println!("After moving first to back: {:?}", map.keys().collect::<Vec<_>>());
}use indexmap::IndexSet;
fn main() {
let mut set = IndexSet::new();
// Insert in order
set.insert("apple");
set.insert("banana");
set.insert("cherry");
// Iterate in insertion order
for value in &set {
println!("{}", value);
}
// Contains
println!("Contains apple: {}", set.contains("apple"));
// Length
println!("Length: {}", set.len());
// Get by index
let item = set.get_index(1);
println!("Index 1: {:?}", item);
// Get index of
let idx = set.get_index_of("banana");
println!("Index of banana: {:?}", idx);
// Remove
set.remove("banana");
println!("After remove: {:?}", set.iter().collect::<Vec<_>>());
// Difference, intersection, etc.
let set1: IndexSet<_> = [1, 2, 3, 4].into_iter().collect();
let set2: IndexSet<_> = [3, 4, 5, 6].into_iter().collect();
// Intersection
let intersection: IndexSet<_> = set1.intersection(&set2).collect();
println!("Intersection: {:?}", intersection);
// Difference
let diff: IndexSet<_> = set1.difference(&set2).collect();
println!("Difference: {:?}", diff);
// Union
let union: IndexSet<_> = set1.union(&set2).collect();
println!("Union: {:?}", union);
}
// IndexSet operations
fn set_operations() {
use indexmap::IndexSet;
let mut a: IndexSet<i32> = [1, 2, 3].into_iter().collect();
let b: IndexSet<i32> = [3, 4, 5].into_iter().collect();
// Insert returns (index, was_new)
let (idx, was_new) = a.insert(4);
println!("Inserted 4 at index {}, new: {}", idx, was_new);
let (idx, was_new) = a.insert(4); // Duplicate
println!("Inserted 4 again at index {}, new: {}", idx, was_new);
// Replace (insert and return old index if existed)
let mut set = IndexSet::new();
set.insert("apple");
set.insert("banana");
let replaced = set.replace("apple");
println!("Replaced: {:?}", replaced);
}use indexmap::IndexSet;
fn main() {
let a: IndexSet<_> = [1, 2, 3].into_iter().collect();
let b: IndexSet<_> = [1, 2, 3].into_iter().collect();
let c: IndexSet<_> = [1, 2, 3, 4].into_iter().collect();
let d: IndexSet<_> = [3, 2, 1].into_iter().collect();
// Equality (order matters!)
println!("a == b: {}", a == b); // true - same elements, same order
println!("a == c: {}", a == c); // false - different elements
println!("a == d: {}", a == d); // false - different order
// Set equivalence (ignoring order)
fn set_eq<T: std::hash::Hash + Eq>(a: &IndexSet<T>, b: &IndexSet<T>) -> bool {
a.len() == b.len() && a.is_subset(b)
}
println!("a equiv d: {}", set_eq(&a, &d)); // true
// Subset/superset
let small: IndexSet<_> = [1, 2].into_iter().collect();
let large: IndexSet<_> = [1, 2, 3, 4].into_iter().collect();
println!("small is_subset of large: {}", small.is_subset(&large));
println!("large is_superset of small: {}", large.is_superset(&small));
}use indexmap::IndexMap;
fn main() {
let mut map: IndexMap<i32, i32> = IndexMap::new();
println!("Initial capacity: {}", map.capacity());
// Reserve capacity
map.reserve(100);
println!("After reserve: {}", map.capacity());
// Shrink to fit
for i in 0..10 {
map.insert(i, i * 2);
}
println!("Len: {}, Capacity: {}", map.len(), map.capacity());
map.shrink_to_fit();
println!("After shrink_to_fit: {}", map.capacity());
// Shrink to minimum capacity
map.shrink_to(5);
println!("After shrink_to(5): {}", map.capacity());
}# Cargo.toml
[dependencies]
indexmap = { version = "2", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Config {
name: String,
settings: IndexMap<String, i32>,
}
fn main() {
let mut config = Config {
name: "test".to_string(),
settings: IndexMap::new(),
};
config.settings.insert("first".to_string(), 1);
config.settings.insert("second".to_string(), 2);
config.settings.insert("third".to_string(), 3);
// Serialize to JSON (preserves order!)
let json = serde_json::to_string_pretty(&config).unwrap();
println!("JSON:\n{}", json);
// Deserialize (preserves order!)
let parsed: Config = serde_json::from_str(&json).unwrap();
println!("\nParsed: {:?}", parsed.settings.keys().collect::<Vec<_>>());
}
// JSON object with preserved order
fn json_ordering() {
use indexmap::IndexMap;
let mut obj: IndexMap<String, serde_json::Value> = IndexMap::new();
obj.insert("z".to_string(), serde_json::json!(1));
obj.insert("a".to_string(), serde_json::json!(2));
obj.insert("m".to_string(), serde_json::json!(3));
let json = serde_json::to_string(&obj).unwrap();
println!("JSON (order preserved): {}", json);
// {"z":1,"a":2,"m":3}
}use indexmap::IndexMap;
use std::collections::HashMap;
fn main() {
// From HashMap to IndexMap
let std_map: HashMap<_, _> = [
("c", 3),
("a", 1),
("b", 2),
].into_iter().collect();
let index_map: IndexMap<_, _> = std_map.into_iter().collect();
println!("From HashMap: {:?}", index_map.keys().collect::<Vec<_>>());
// From IndexMap to HashMap
let std_map: HashMap<_, _> = index_map.into_iter().collect();
println!("To HashMap (unordered iteration)");
// From Vec of tuples
let vec = vec![("x", 1), ("y", 2), ("z", 3)];
let map: IndexMap<_, _> = vec.into_iter().collect();
println!("From Vec: {:?}", map.keys().collect::<Vec<_>>());
// To Vec
let map = IndexMap::from([
("a", 1),
("b", 2),
("c", 3),
]);
let keys: Vec<_> = map.keys().collect();
let values: Vec<_> = map.values().collect();
let entries: Vec<_> = map.into_iter().collect();
println!("Keys: {:?}", keys);
println!("Values: {:?}", values);
println!("Entries: {:?}", entries);
}
// From arrays and slices
fn from_collections() {
use indexmap::IndexMap;
// From array
let map = IndexMap::from([
("a", 1),
("b", 2),
]);
// From parallel arrays
let keys = ["a", "b", "c"];
let values = [1, 2, 3];
let map: IndexMap<_, _> = keys.into_iter().zip(values).collect();
println!("Zipped: {:?}", map);
}use indexmap::IndexMap;
#[derive(Debug, Clone)]
struct Config {
name: String,
options: IndexMap<String, String>,
}
impl Config {
fn new(name: &str) -> Self {
Self {
name: name.to_string(),
options: IndexMap::new(),
}
}
fn set(&mut self, key: &str, value: &str) -> &mut Self {
self.options.insert(key.to_string(), value.to_string());
self
}
fn get(&self, key: &str) -> Option<&String> {
self.options.get(key)
}
fn remove(&mut self, key: &str) -> Option<String> {
self.options.remove(key)
}
fn keys(&self) -> impl Iterator<Item = &String> {
self.options.keys()
}
fn to_ordered_pairs(&self) -> Vec<(&String, &String)> {
self.options.iter().collect()
}
}
fn main() {
let mut config = Config::new("my-app");
// Set options in specific order
config
.set("host", "localhost")
.set("port", "8080")
.set("debug", "true")
.set("timeout", "30");
println!("Config: {}", config.name);
for (key, value) in config.to_ordered_pairs() {
println!(" {} = {}", key, value);
}
// Override preserves position
config.set("host", "0.0.0.0");
println!("\nAfter override:");
for key in config.keys() {
println!(" {}", key);
}
}use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct ApiResponse {
status: String,
data: IndexMap<String, serde_json::Value>,
}
fn main() {
let mut response = ApiResponse {
status: "success".to_string(),
data: IndexMap::new(),
};
// Add fields in specific order
response.data.insert("id".to_string(), serde_json::json!(42));
response.data.insert("name".to_string(), serde_json::json!("Alice"));
response.data.insert("email".to_string(), serde_json::json!("alice@example.com"));
response.data.insert("active".to_string(), serde_json::json!(true));
// JSON output preserves field order
let json = serde_json::to_string_pretty(&response).unwrap();
println!("{}", json);
}
// Template with ordered placeholders
struct Template {
placeholders: IndexMap<String, String>,
}
impl Template {
fn new() -> Self {
Self {
placeholders: IndexMap::new(),
}
}
fn add(&mut self, key: &str, default: &str) {
self.placeholders.insert(key.to_string(), default.to_string());
}
fn render(&self, values: &IndexMap<String, String>) -> String {
let mut result = String::new();
for (key, default) in &self.placeholders {
let value = values.get(key).unwrap_or(default);
result.push_str(&format!("{}: {}\n", key, value));
}
result
}
}
fn template_example() {
let mut template = Template::new();
template.add("greeting", "Hello");
template.add("name", "World");
template.add("punctuation", "!");
let mut values = IndexMap::new();
values.insert("name".to_string(), "Rust".to_string());
println!("{}", template.render(&values));
}use indexmap::IndexMap;
struct LruCache<K, V> {
capacity: usize,
cache: IndexMap<K, V>,
}
impl<K: std::hash::Hash + Eq + Clone, V: Clone> LruCache<K, V> {
fn new(capacity: usize) -> Self {
Self {
capacity,
cache: IndexMap::new(),
}
}
fn get(&mut self, key: &K) -> Option<&V> {
// Move to end (most recently used)
if let Some(idx) = self.cache.get_index_of(key) {
let (k, v) = self.cache.swap_remove_index(idx).unwrap();
self.cache.insert(k, v);
return self.cache.get(key);
}
None
}
fn put(&mut self, key: K, value: V) {
// Remove if exists
if let Some(_) = self.cache.swap_remove(&key) {
// Already removed
}
// Evict oldest if at capacity
if self.cache.len() >= self.capacity {
self.cache.shift_remove_index(0); // Remove first (oldest)
}
self.cache.insert(key, value);
}
fn len(&self) -> usize {
self.cache.len()
}
fn is_empty(&self) -> bool {
self.cache.is_empty()
}
}
fn main() {
let mut cache = LruCache::new(3);
cache.put("a", 1);
cache.put("b", 2);
cache.put("c", 3);
println!("Cache size: {}", cache.len());
// Access "a" - moves to most recent
cache.get(&"a".to_string());
// Add new item - evicts "b" (oldest after access)
cache.put("d", 4);
println!("After adding d, has a: {}", cache.get(&"a".to_string()).is_some());
println!("Has b: {}", cache.get(&"b".to_string()).is_some()); // false - evicted
println!("Has c: {}", cache.get(&"c".to_string()).is_some()); // true
println!("Has d: {}", cache.get(&"d".string()).is_some()); // true
}IndexMap preserves insertion order, unlike HashMapIndexSet is an ordered version of HashSet.get_index(n) to access by position.get_index_of(key) to find position of a key.swap_remove() for O(1) removal (changes order).shift_remove() for O(n) removal (preserves order).sort_keys() to sort by key in place.sort_by() for custom sorting.swap_indices(i, j) to swap elements by position.move_index(from, to) to move an elementHashMap with or_insert, and_modify, etc.IndexSet supports set operations: intersection, union, differenceHashMap for order tracking