简体   繁体   中英

Is there HashSet which implements NavigableSet in Java?

I need to parse some site for a list of users and their posts. Users are represented by UserIds, and posts by PostIds, which are actually integers. So I create a class for user like this:

class User {
    private int userId;
    private List<Integer> postList;
    //...
}

And then I'm encountering a problem. This site provides an api, which returns a list of post structures like:

class Post {
    int postId;
    int postAuthorId;
    String postText;
    //...
}

So I should get a post, search if I already have post author (user) in my user set, if no, add new user and post ids to user set, if yes - add post id to the list of this user posts. Firstly I wanted to use HashSet - because of quick add and search methods. But then I realized that I can't get desired user from HashSet . Next I thought about TreeSet , which implements NavigableSet , so I can use TreeSet.ceiling(user) . It returns object, so I can modify it. It all is fine, but HashSet is much faster than TreeSet . So the question is, if there is some kind of HashSet which can return specific objects, like if it was implementing NavigableSet ? Or I just should rewrite my code somehow? Will be grateful for ideas.

The reason that HashSet is faster is that it's not sorted. A NavigableSet needs to be sorted, and any implementation will necessarily have some overhead in keeping the set ordered. TreeSet is probably the best general-purpose sorted-set implementation available, and if you need the features that NavigableSet brings, you'll need to pay the performance cost. I'm quite skeptical that the overhead in the set lookups is the sticking point in your program in any case.

From the NavigableSet Javadoc,

All Known Implementing Classes: ConcurrentSkipListSet , TreeSet

And since a hash function destroys any kind of natural ordering I think a NavigableSet would be impossible with basic hashing.

As an extension to my comment, this sounds like a practical use of HashMap. You can use the user id in User as the key, and map to the User object. Using what you've given us, the below code would populate the users HashMap.

HashMap<Integer, User> users = new HashMap<>();

for(Post post : posts) {
    int userId = post.getPostAuthorId();
    if(users.get(userId) != null) {
        users.get(userId).addPost(post);
    }
    else {
        users.put(userId, new User(userId));
    }
}

You should probably keep your list of Users and your list of posts separate. Then use maps that suit your purposes to associate them. If you use something like hibernate with it, you'll be able to keep using them as POJOs and get persistence out of it as well.

If you want to keep the posts inside the user you probably would also rewrite the Hash function of your User class so that the class would be ID'd by the userID alone and not the posts. (As well as rewriting equals )

Some more on that here Why is the default hashcode() in java bad?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM