Question

I have two Collection objects, I want to associate each object of these two in a readable way (HashMap, Object created on purpose, you choose).

I was thinking of two loops one nested into the other, but maybe it's a well known problem and has a commonly understandable solution...

What if the number of Collection objects raises above two?

EDIT after Joseph Daigle comment: The items of the Collection objects are all of the same type, they are rooms of hotels found to be bookable under certain conditions.

Collection<Room> roomsFromA = getRoomsFromA();
Collection<Room> roomsFromB = getRoomsFromB();
for(Room roomA : roomsFromA){
    for(Room roomB : roomsFromB){
        //add roomA and roomB to something, this is not important for what I need
        //the important part is how you handle the part before
        //especially if Collection objects number grows beyond two
    }
}

EDIT 2: I'll try to explain better, sorry for the question being unclear. Follows an example: A user requests for a double and a single room. The hotel has 3 double and 4 single rooms available.

I need to associate every "double room" to every "single room", this is because each Room has its own peculiarity say internet, a more pleasant view, and so on. So i need to give the user all the combinations to let him choose.

This is the simple case, in which only two Collection of Room objects are involved, how do you manage the problem when say both hotel and user can offer / request more Room types?

Was it helpful?

Solution

What you are trying to do here is to get all possible permutations of choosing X from a set of Y. This is a well known problem in discrete mathematics and I think it is just called Combinatorial Mathematics.

To solve your problem you need to create a super collection containing all your Room types. If this is an array or a List you can then use this example to calculate all possible ways of choosing X from the set of Y. The example will give you the indices from the list/array.

OTHER TIPS

Do the collections line up exactly?

HashMap map = new HashMap();
for (int i=0; i<c1.Size(); i++) {
   map.put(c1[i], c2[i]);
}

Well, since I don't know if you will need to search for both of them having only one, the HashMap won't work.

I would create a class that receives a Pair.. sort of:

private static class Pair<K, T> {
    private K one;
    private T two;

    public Pair(K one, T two) {
        this.one = one;
        this.two = two;
    }

    /**
     * @return the one
     */
    public K getOne() {
        return one;
    }

    /**
     * @return the two
     */
    public T getTwo() {
        return two;
    }
} 

And create a List with them.

Your example implies that the return value from "roomsFromB" is a subcollection of the return value of "roomsFromA", so it'd be more natural to model it that way:

class Room {
   public Collection<Room> getRoomsFromB { ... 
}

which would then let you do :

//Collection rooms

for (Room a: rooms)
{ 
   for(Room b a.getRoomsFromB){ ...

This is assuming that they're modeled hierarchically, of course. If they're not then this is inappropriate, but then the question you're asking, it seems to me, is really how to model the relationship between them, and you haven't yet made that explicit.

You might reconsider whether you need exactly this logic. You're introducing an O(n^2) operation, which can quickly get out of hand. (Technically O(mn), but I'm guessing m and n are roughly the same order.)

Is there another solution to your problem? Perhaps you could create a 'set' which includes all of A and all of B, and then each object in A and B could point to this set, instead?

I assume that:

  • Each element in collection 1 will match a single element in collection 2
  • The collections have the same size
  • The collections can be ordered and the order matches each element in both collections

  1. Order both collections (in the same order) by the property that identifies each object.
  2. Iterate through both collections with a single loop, build a relation object and add it into a new collection.

See if this helps you:

public static class Room {
    private int number;
    private String name;

    public Room(int number, String name) {
        super();
        this.number = number;
        this.name = name;
    }

    public int getNumber() {
        return number;
    }

    public String getName() {
        return name;
    }
}

public static class RoomRelation {
    private Room a;
    private Room b;

    public RoomRelation(Room a, Room b) {
        super();
        this.a = a;
        this.b = b;
    }

    public Room getA() {
        return a;
    }

    public Room getB() {
        return b;
    }

    @Override
    public String toString() {
        return a.getName() + "(" + a.getNumber() + ") " + b.getName() + "(" + b.getNumber() + ")";
    }
}

public static void main(String[] args) {

    List<Room> roomsFromA = new ArrayList<Room>();
    List<Room> roomsFromB = new ArrayList<Room>();

    roomsFromA.add(new Room(1,"Room A"));
    roomsFromA.add(new Room(2,"Room A"));

    roomsFromB.add(new Room(1,"Room B"));
    roomsFromB.add(new Room(2,"Room B"));

    Comparator<Room> c = new Comparator<Room>() {
        @Override
        public int compare(Room o1, Room o2) {
            return o1.getNumber() - o2.getNumber();
        } };

    Collections.sort(roomsFromA, c);
    Collections.sort(roomsFromB, c);

    List<RoomRelation> relations = new ArrayList<RoomRelation>();

    for (int i = 0; i < roomsFromA.size(); i++) {
        relations.add(new RoomRelation(roomsFromA.get(i), roomsFromB.get(i)));
    }

    for (RoomRelation roomRelation : relations) {
        System.out.println(roomRelation);
    }
}

Your question is quite unclear. As I understand you want to list all combinations of rooms, minus duplicates. Here us some code to build up a 2d array of all the room combinations. For more kinds of room, put in another nested loop.

Collection<Room> roomsFromA = getRoomsFromA();
Collection<Room> roomsFromB = getRoomsFromB();

Room[][] combinations = new Room[roomsFromA .size()][roomsFromB .size()];

int a = 0;
int b = 0;

for(Room roomA : roomsFromA){

   for(Room roomB : roomsFromB){
      combinations [a][b] = [roomA][roomB]; //Build up array
      b++; 
   }
   a++;
}

return combinations;

It is a common problem. It's called a Cartesian product. If you have two collections like in your case, I would not hesitate to have two nested loops. Otherwise, see this question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top