Is there a Java map keyset () equivalent to C’s STD:: map?

Is there a @ l_ 404_ 0 @ map keyset() is equivalent to C's STD:: map?

The Java keyset() method returns "a set view of the keys contained in this map."

Solution

All the answers presented so far end up creating an STD:: set directly, which may not be ideal: if you only want to be able to iterate keys, you don't want to create a new container

A more flexible option is to use a conversion iterator, which converts an STD:: Map iterator to some type of iterator, which generates keywords when dereferencing This is very simple to use the 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>()
    );
}

Using these utilities, you can convert any range of STD:: Map iterators (or iterators to any other pair of associated containers) to a range of only one key for instance:

#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,","));
}

The program outputs:

1,2,3,

If you really want an STD:: set containing keys, you can easily create one using these iterators:

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

Overall, this is a more flexible solution

If you don't have boost or don't want to use boost or can't use boost, this specific transform iterator can be easily implemented:

#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());   }

This usage is the same as the boost version

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>