blob: 28300ccb9c07d54089872ee0326130ca2e1b8173 [file] [log] [blame]
/*
* Copyright 2024-present Alibaba Inc.
*
* Licensed 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