views:

139

answers:

8

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?

A: 

Do the collections line up exactly?

HashMap map = new HashMap();
for (int i=0; i<c1.Size(); i++) {
   map.put(c1[i], c2[i]);
}
AgileJon
Please, always use the interface, never the class.. giving: Map map = new HashMap(); The raw form is discouraged to
José Leal
No, this is not what I need, I need to add all items of the Collection objects, each item of each Collection object has to be associated which each item of the other Collection objects
Alberto Zaccagni
Also, there is no guarantee that the Collection is an array. A lookup on a LinkedList without using the iterator is slow.
Joshua
A: 

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.

José Leal
A: 

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.

Steve B.
A: 

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);
 }
}
bruno conde
A: 

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?

Alex Feinman
A: 

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;
ewh105
A: 

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.

waxwing
That is not quite what he wants
willcodejavaforfood
I think it is. I am answering the part of the question: '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..[...]I need to associate every "double room" to every "single room"'.How is this not a Cartesian product? As for how to store it, an example is given in the linked question.
waxwing
+1  A: 

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.

willcodejavaforfood