views:

317

answers:

2

Hey guys,

Quite new to Java so this is probably pretty straight forward. I want to sort an ArrayList in the class MediaLib based on the natural order of a specified key. I cant work out how to use my comparator (compareTo(MediaInterface, key)) which is in the Media class. Whats the best way to go about this?

package assign1;

import java.util.*;

public class Media implements MediaInterface {

    private Map<String, Object> fields;
    private static int compare;

 public Media(String title, String format) {
     fields = new TreeMap<String, Object>();
     fields.put("title", title);
     fields.put("format", format);
 }


 public Object get(String key) {
  return fields.get(key);
 }


 public void put(String key, Object value) {
  fields.put(key, value);
 }


 public boolean hasKeywords(String[] words, boolean combineWithAND) {
     Collection<Object> values = (Collection<Object>) fields.values();
     int count = 0;
  int size = 0;
  for (String s: words) {
         for (Object o: values) {
                String t = o.toString();
                if (t.indexOf(s) >= 0) {
                    count++;
                    break;
                }
         }
         size++;
  }
  if ((count == 0 && !combineWithAND) || (combineWithAND && (count != size))) {
      return false;
  }
  return true;
 }


 public int compareTo(MediaInterface mi, String key) { //<<<<<<<------calling this!!
  if (mi == null)
   throw new NullPointerException();
  Media m = (Media) mi;
  Comparable mValue = (Comparable) m.get(key);
  Comparable lValue = (Comparable) fields.get(key);
  if ((mValue == null) && (lValue == null)){
      return 0;
  }
  if ((lValue == null)){
            return 1;
        }
  if ((mValue == null)){
            return -1;
        }
  return (lValue).compareTo(mValue);
 }


 @Override
 public int compareTo(MediaInterface mi) {
  if (mi == null)
   throw new NullPointerException();
  Media m = (Media) mi;
  Set<String> lSet = fields.keySet();
  if (compareTo(m, "title") != 0) {
      return compareTo(m, "title");
  }
  if (compareTo(m, "year") != 0) {
            return compareTo(m, "year");
        }
  for (String s: lSet) {
      if (compareTo(m, s) != 0) {
          return compareTo(m, s);
      }
  }
  return 0;
 }


 public boolean equals(Object object) {
  if (object == null)
   return false;
  if (!(object instanceof Media))
   return false;
  Media m = (Media) object;
  if (compareTo(m) != 0) {
      return false;
  }
  return true;
 }
}

    package assign1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;

public class MediaLib implements Searchable {
 private ArrayList<MediaInterface> media;

 public MediaLib() {
  media = new ArrayList<MediaInterface>();
 }


 @Override
 public void add(MediaInterface mi) {
  if (media.isEmpty()) {
      media.add(mi);
  }
  else {
      for (MediaInterface m: media) {
          if (mi.equals(m)) {
              return;
          }
      }
      media.add(mi);
  }
 }


 @Override
 public boolean contains(MediaInterface mi) {
     for (MediaInterface m: media) {
            if (mi.equals(m)) {
                return true;
            }
        }
     return false;
 }


 @Override
 public Collection<MediaInterface> findByKeyword(String[] words, boolean combineWithAND) {
  Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
     for (MediaInterface mi: media) {
      if (mi.hasKeywords(words, combineWithAND)) {
          foundList.add(mi);
      }
  }
     return foundList;
 }


 @Override
 public Collection<MediaInterface> findByTitle(String str) {
     Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
        for (MediaInterface mi: media) {
            if ((mi.get("title")).equals(str)) {
                foundList.add(mi);
            }
        }
        return foundList;
 }


 @Override
 public Collection<MediaInterface> getAllWithFormat(String formatName) {
     Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
        for (MediaInterface mi: media) {
            if ((mi.get("format")).equals(formatName)) {
                foundList.add(mi);
            }
        }
        return foundList;
 }

 public Collection<MediaInterface> getAll() {
     Collection<MediaInterface> fullList = new ArrayList<MediaInterface>();
        for (MediaInterface mi: media) {
            fullList.add(mi);
        }
        return fullList;
 }


 @Override
 public void removeAllWithKeyword(String[] words, boolean combineWithAND) {
     Collection<MediaInterface> foundList = findByKeyword(words, combineWithAND);
     for (MediaInterface mi: foundList) {
         media.remove(mi);
     }
 }


 @Override
 public void removeAllWithFormat(String format) {
     Collection<MediaInterface> foundList = getAllWithFormat(format);
        for (MediaInterface mi: foundList) {
            media.remove(mi);
        }
 }


 @Override
 public void sort() {
     Collections.sort(media);
 }


 @Override
 public void sort(final String fieldName) {  
     Collections.sort(media, new Media.compareTo(MediaInterface, fieldName))  //<<<<<--------Trying to call compareTo()

     }
 }


 public void parse(java.io.BufferedReader br) throws java.io.IOException {
     while(br.readLine()!= null) {
         Media mi = new Media(/n br.readLine(), br.readLine());
         while 

     }
 }
}
A: 

You have two options to compare objects, and you are not using any of them current:

  • implement Comparable<YourType>. Then the compiler will force you to implement

    public int compareTo(YourType other) {
       // put comparison logic between "this" and "other" here
    }
    
  • create a class that implements Comparator<YourType>. Then you will have to implement:

    public int compare(YourType first, YourType second) {
        // comparison logic here
    }
    

If you use the first option, you can use Collections.sort(list). If you use the second option, you use Collections.sort(list, new YourTypeComparator()) (actually, it is good to have only one instance of a Comparator and reuse it, but I'll spare the details for brevity)

Bozho
+1  A: 

You already implement the Comparable interface in your MediaInterface class, this is a generic interface, so you then implement Comparable<MediaInterface> which will then require you to implement a method with the signature

public int compareTo(final MediaInterface other)

This is why your call to Collections.sort(media); compiles

In order to sort by a specific field name, you need to provide an instance of a Comparator, the easiest way to do this will be to create an inner class in your Media class which you can then pass into Collections.sort. For example

public class Media implements MediaInterface {
    public static final class FieldComparator implements Comparator<Media> {
        private final String field;

        public FieldComparator(final String field) {
            this.field = field;
        }

        public int compare(final Media a, final Media b) {
            // implementation to compare a.field to b.field
        }
    }
}

You can then rewrite your second sort method as

@Override
public void sort(final String fieldName) {  
    Collections.sort(media, new Media.FieldComparator(fieldName));
}
Jon Freedman
thanks Jon, I thought id have to add something to media....works great, thanks
Milk