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

是否有一个Java Map keySet()等效于C ++的std::map

Java keySet()方法返回“此映射中包含的键的设置视图”。

到目前为止提供的所有答案最终都会直接创建一个std::set ,这可能并不理想:如果您只想迭代键,那么您不希望有创建全新的开销。容器。

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

 #include  #include  // You may already have a select1st implementation; if not, you should :-) template  struct select1st : std::unary_function { const typename Pair::first_type& operator()(const Pair& p) const { return p.first; } }; template  boost::transform_iterator< select1st, typename C::const_iterator > begin_keys(const C& c) { return boost::make_transform_iterator( c.begin(), select1st() ); } template  boost::transform_iterator< select1st, typename C::const_iterator > end_keys(const C& c) { return boost::make_transform_iterator( c.end(), select1st() ); } 

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

 #include  #include  #include  int main() { std::map 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(std::cout, ",")); } 

该计划输出:

 1,2,3, 

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

 std::set s(begin_keys(m), end_keys(m)); 

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

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

 #include  template  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  key_iterator begin_keys(const C& c) { return key_iterator(c.begin()); } template  key_iterator end_keys(const C& c) { return key_iterator(c.end()); } 

此用法与Boost版本相同。

这是一个一位一字的class轮:

 map m; ... // Useful stuff goes here ... set s; transform(m.begin(), m.end(), inserter(s, s.begin()), select1st >()); 

如果你没有select1st

 template  struct select1st : public std::unary_function { const typename P::first_type& operator()(const P &arg) const { return arg.first; } }; 

也许以下可能有用:

 #include  #include  #include  #include  #include  #include  template< class Key, class T, class Comparator, class MapAllocator, class SetAllocator> void make_key_set(const std::map& map, std::set& set) { set.clear(); typedef typename std::map map_type; typename map_type::const_iterator itr = map.begin(); while (map.end() != itr) { set.insert((itr++)->first); } } int main() { std::map m; m["one"] = 1.1; m["two"] = 2.2; m["three"] = 3.3; std::set key_set; make_key_set(m,key_set); std::copy(key_set.begin(), key_set.end(), std::ostream_iterator(std::cout, "\n")); return 0; } 

使用STL兼容序列(如std :: vector,std :: deque或std :: list)的make_key_set函数的重载可以如下所示:

 template< class Key, class T, class Comparator, class MapAllocator, class SeqAllocator, template class Sequence> void make_key_set(const std::map& map, Sequence& sequence) { sequence.clear(); typedef typename std::map map_type; typename map_type::const_iterator itr = map.begin(); while (map.end() != itr) { sequence.push_back((itr++)->first); } } 

你可以自己实现它:

 vector keys; for (map::iterator it=m.begin(); it!=m.end; it++) keys.push_back(it->first) 

Boost.Range将此提供为boost :: adapters :: map_values :

 std::map my_map; for (auto &value : my_map | boost::adaptors::map_values) { //... }