blob: f831756e68556f31da5985d3c454d9a5f3ecd639 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#pragma once
#include <cstddef>
#include <iterator>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
namespace paimon {
template <typename K, typename V>
class LinkedHashMap {
public:
using IteratorType = typename std::list<std::pair<K, V>>::iterator;
using ConstIteratorType = typename std::list<std::pair<K, V>>::const_iterator;
LinkedHashMap() = default;
LinkedHashMap(const LinkedHashMap& other) {
order_ = other.order_;
map_.clear();
for (auto iter = order_.begin(); iter != order_.end(); ++iter) {
map_[iter->first] = iter;
}
}
LinkedHashMap& operator=(const LinkedHashMap& other) {
order_ = other.order_;
map_.clear();
for (auto iter = order_.begin(); iter != order_.end(); ++iter) {
map_[iter->first] = iter;
}
return *this;
}
bool operator==(const LinkedHashMap& other) const {
if (this == &other) {
return true;
}
return map_.size() == other.map_.size() && order_ == other.order_;
}
bool operator!=(const LinkedHashMap& other) const {
return !(*this == other);
}
size_t size() const {
return order_.size();
}
bool empty() const {
return order_.empty();
}
IteratorType erase(const K& key) {
if (!map_.count(key)) {
return order_.end();
}
auto iter = order_.erase(map_[key]);
map_.erase(key);
return iter;
}
IteratorType insert(const K& key, const V& value) {
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
}
return unsafe_insert(key, value);
}
IteratorType insert_or_assign(const K& key, const V& value) {
auto iter = map_.find(key);
if (iter != map_.end()) {
// if key exists, update its value
iter->second->second = value;
return iter->second;
}
return unsafe_insert(key, value);
}
ConstIteratorType find(const K& key) const {
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
}
return order_.end();
}
ConstIteratorType begin() const {
return order_.begin();
}
ConstIteratorType end() const {
return order_.end();
}
V& operator[](const K& key) {
auto iter = map_.find(key);
if (iter != map_.end()) {
// if key exists, return its value reference
return iter->second->second;
}
return unsafe_insert(key, V())->second;
}
std::unordered_set<K> key_set() const {
std::unordered_set<K> key_set;
for (const auto& [key, _] : order_) {
key_set.insert(key);
}
return key_set;
}
std::vector<K> key_vec() const {
std::vector<K> key_vec;
key_vec.reserve(order_.size());
for (const auto& [key, _] : order_) {
key_vec.push_back(key);
}
return key_vec;
}
private:
IteratorType unsafe_insert(const K& key, const V& value) {
auto new_iter = order_.insert(order_.end(), {key, value});
map_[key] = new_iter;
return new_iter;
}
// map_ {key, iterator in order}
std::unordered_map<K, IteratorType> map_;
std::list<std::pair<K, V>> order_;
};
} // namespace paimon