0

In a social media, suppose each user is represented like below:

public class User {
    private int userId;
    private List<User> friendsList;

    User(int id) {
        this.userID = id;
        this.friendsList = new LinkedList<>();
    }

    void addFriend(User a) {
        this.friendsList.add(a);
    }

    int getUserId() {
        return this.userID;
    }

    List<User> getFriendsList() {
        return this.friendsList;
    }
}

if A and B are friends(A->B), then A will be added to B's friend list and B will be added to A's friend list.

A.addFriend(B);
B.addFriend(A);

How i can efficiently find two users X and Y are connected by using Java 8 steam methods ?

ie if X->p->q->r->s->Y, then

bool isConnected(User X, User Y) should return true 
Here X and Y are connected through common friends p, q, r and s.
geisterfurz007
  • 5,292
  • 5
  • 33
  • 54
  • 4
    Is your question about streams, or the general algorithm? How would you do it without streams? – John Kugelman Aug 03 '18 at 11:40
  • I am particularly looking for - how to do it with java streams. if there is a million users, how efficiently we can find it using java streams. – Vinod Kunnakkattil Aug 03 '18 at 11:42
  • 1
    What does your non-stream solution look like? Why do you want to improve it? This isn't really a natural fit for streams. – John Kugelman Aug 03 '18 at 12:12
  • You absolutely need to add a parameter to limit connection level, for example, after 6 level stop reaserach. If you dont do that the complexity is exponential, you can also change something in data structure – Frighi Aug 04 '18 at 14:06
  • What was your non-stream solution? – treo Mar 30 '20 at 00:43

3 Answers3

0

You would need a way to keep track of the object that was visited or else you will go in loops.

public bool NodeVisited { get; private set; }

boolean isConnected(User a, User b){
    for(final User u : a.getFriendsList()){
          if(NodeVisited  == false){
            NodeVisited  = true;
            if(u.getUserId() == b.getUserId() || isConnected(u, b)){
              return true;
            }
            } 
           else continue;
   }
return false;

}

0

The close problem to "Find the shortest way (if any) between 2 points in a labyrinth."
Main idea:

  1. Spread 2 waves from 2 points (or 2 friends) which cover near points (friends)
  2. Remember only(!) previous layers of points (friends) to restrict the future spreading out of the wave in that directions
  3. After each spreading out step check wawes intersection for common points (friends)
  4. Repeat until getting intersections of waves or 1 wave will be stopped: there are no new directions to spread except in backward directions from the previous step.

P.S.: The most optimal algorithm involves "several" (depends on data) spots of wave spreading processes.

https://github.com/Dimoniada/FriendsProblem

-1

You don't really have to use streams, but just a simple for-loop and recursion:

boolean isConnected(User a, User b){
    for(final User u : a.getFriendsList()){
        if(u.getUserId() == b.getUserId() || isConnected(u, b)){
            return true;
        }
    }
    return false;
}

If you still want to use streams, you can use this snippet (still uses recursion though):

boolean isConnected(User a, User b){
    return a.getFriendsList()
        .stream()
        .anyMatch(u -> u.getUserId() == b.getUserId() || isConnected(u, b));
}
Lino
  • 19,604
  • 6
  • 47
  • 65
  • This isn't really an answer to the question - you're not checking a graph to see if they're connected, you're checking lists of lists. This could lead to a stack overflow - check user A's friends list, check user B's, then check user A's, then B, then A, and so on – treo Mar 28 '20 at 22:26