java - 是否有与 C++ 的 std::map 等效的 Java Map keySet()?

标签 java c++ stl stdmap

是否有与 C++ 的 std::map 等效的 Java Map keySet()?

Java keySet() 方法返回 "a set view of the keys contained in this map."

最佳答案

目前给出的所有答案最终都直接创建了一个 std::set,这可能并不理想:如果您只想迭代键,则不会想要有创建一个全新容器的开销。

一个更灵活的选择是使用转换迭代器,将 std::map 迭代器转换为某种类型的迭代器,该迭代器仅在取消引用时产生键。使用 Boost Transform Iterator 非常简单:

#include <functional>
#include <boost/iterator/transform_iterator.hpp>

// You may already have a select1st implementation; if not, you should :-)
template <typename Pair>
struct select1st
    : std::unary_function<const Pair&, const typename Pair::first_type&>
{
    const typename Pair::first_type& operator()(const Pair& p) const 
    { 
        return p.first; 
    }
};

template <typename C>
boost::transform_iterator<
    select1st<typename C::value_type>, typename C::const_iterator
> begin_keys(const C& c) 
{ 
    return boost::make_transform_iterator(
        c.begin(), select1st<typename C::value_type>()
    );
}

template <typename C>
boost::transform_iterator<
    select1st<typename C::value_type>, typename C::const_iterator
> end_keys(const C& c) 
{ 
    return boost::make_transform_iterator(
        c.end(), select1st<typename C::value_type>()
    );
}

使用这些实用函数,您可以将任意范围的 std::map 迭代器(或迭代器到您可能拥有的任何其他对关联容器中)转换为仅包含键的范围。例如:

#include <iostream>
#include <iterator>
#include <map>

int main()
{
    std::map<int, int> m;
    m.insert(std::make_pair(1, 2));
    m.insert(std::make_pair(2, 4));
    m.insert(std::make_pair(3, 6));

    std::copy(
        begin_keys(m), end_keys(m), 
        std::ostream_iterator<int>(std::cout, ","));
}

这个程序输出:

1,2,3,

如果您真的想要一个包含键的 std::set,您可以使用这些迭代器轻松地创建一个:

std::set<int> s(begin_keys(m), end_keys(m));

总的来说,这是一个更灵活的解决方案。

如果您没有 Boost 或者不想使用 Boost 或者不能使用 Boost,这个特定的转换迭代器可以很容易地实现:

#include <iterator>

template <typename C>
class key_iterator
    : public std::iterator<
          std::bidirectional_iterator_tag, 
          typename C::key_type, 
          typename C::difference_type, 
          typename C::pointer, 
          typename C::reference
      >
{
public:

    key_iterator() { }
    explicit key_iterator(typename C::const_iterator it) : it_(it) { }

    typename const C::key_type& operator*() const  { return  it_->first; }
    typename const C::key_type* operator->() const { return &it_->first; }

    key_iterator& operator++() { ++it_; return *this; }
    key_iterator operator++(int) { key_iterator it(*this); ++*this; return it; }

    key_iterator& operator--() { --it_; return *this; }
    key_iterator operator--(int) { key_iterator it(*this); --*this; return it; }

    friend bool operator==(const key_iterator& lhs, const key_iterator& rhs)
    {
        return lhs.it_ == rhs.it_;
    }

    friend bool operator!=(const key_iterator& lhs, const key_iterator& rhs)
    {
        return !(lhs == rhs);
    }

private:

    typename C::const_iterator it_;
};

template <typename C>
key_iterator<C> begin_keys(const C& c) { return key_iterator<C>(c.begin()); }

template <typename C>
key_iterator<C> end_keys(const C& c)   { return key_iterator<C>(c.end());   }

此用法与 Boost 版本相同。

关于java - 是否有与 C++ 的 std::map 等效的 Java Map keySet()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2467000/

相关文章:

c++ - 为什么发布版本 memset 比 visual studio 2012 中的调试版本慢?

c++ - next_permutation 返回奇怪的结果

c++ - 我如何有效地在元素之前和之后搜索关键短语

java - 当我们允许注入(inject)时如何管理 ExecutorService 的关闭?

c++ - 图的节点类(C++)

java - 我如何接收数据报包

c++ - 为什么 `std::array::at()` 没有实现为模板函数?

c++ - 带 lambda 谓词的 std::remove_if

java - PriorityQueue 未在添加时排序

java - 聊天应用程序问题