What is the equivalent of a LinkedHashSet (Java) in C#?
HashSet does the job because it is virtually equivalent to LinkedHashSet in Java. HashSet is backed by a linked list - though the docs don't explicitly state that it preserves the order or that it is backed by a array-based linked list. You can see from the source code the implementation is a LinkedHashSet.
Duplicates are not allowed just like the Java LinkedHashSet. The one difference between this and LinkedHashSet is that if you remove something from the set, it only marks the element as free in the array, and so adding an item after a remove() fills up the empty array slots first before “appending”. The way around this is to call the TrimExcess() method. So, while it is not exactly the same in many use cases, e.g. serialize and deserialize and for effectively immutable sets once created it works great.
You can always subclass and override remove() to always call TrimExcess() to get the same behavior. And you can name the class LinkedHashSet for clarity!
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
String[] crew = {"Spock", "Kirk", "Bones", "Picard", "Uhura", "Chekov"};
HashSet<String> linkedHashSet = new HashSet<String>(crew);
// Show order is preserved
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
// Remove from the middle
linkedHashSet.Remove("Picard");
Console.WriteLine();
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
// Add it back but it is back in the middle not the end
linkedHashSet.Add("Picard");
Console.WriteLine();
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
// Remove and trim then add
linkedHashSet.Remove("Picard");
linkedHashSet.TrimExcess();
linkedHashSet.Add("Picard");
Console.WriteLine();
foreach(String value in linkedHashSet){
Console.Write(value); Console.Write(" ");
}
Console.WriteLine();
}
}
}
Output:
Spock Kirk Bones Picard Uhura Chekov
Spock Kirk Bones Uhura Chekov
Spock Kirk Bones Picard Uhura Chekov
Spock Kirk Bones Uhura Chekov Picard
I completed the unfinished methods and generally polished the class that 'achitaka-san' posted.
public class LinkedHashSet<T> : ISet<T> {
private readonly IDictionary<T, LinkedListNode<T>> dict;
private readonly LinkedList<T> list;
public LinkedHashSet(int initialCapacity) {
this.dict = new Dictionary<T,LinkedListNode<T>>(initialCapacity);
this.list = new LinkedList<T>();
}
public LinkedHashSet() {
this.dict = new Dictionary<T,LinkedListNode<T>>();
this.list = new LinkedList<T>();
}
public LinkedHashSet(IEnumerable<T> e) : this() {
addEnumerable(e);
}
public LinkedHashSet(int initialCapacity, IEnumerable<T> e) : this(initialCapacity) {
addEnumerable(e);
}
private void addEnumerable(IEnumerable<T> e) {
foreach (T t in e) {
Add(t);
}
}
//
// ISet implementation
//
public bool Add(T item) {
if (this.dict.ContainsKey(item)) {
return false;
}
LinkedListNode<T> node = this.list.AddLast(item);
this.dict[item] = node;
return true;
}
public void ExceptWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
Remove(t);
}
}
public void IntersectWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
T[] ts = new T[Count];
CopyTo(ts, 0);
foreach (T t in ts) {
if (!System.Linq.Enumerable.Contains(other, t)) {
Remove(t);
}
}
}
public bool IsProperSubsetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
int contains = 0;
int noContains = 0;
foreach (T t in other) {
if (Contains(t)) {
contains++;
} else {
noContains++;
}
}
return contains == Count && noContains > 0;
}
public bool IsProperSupersetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
int otherCount = System.Linq.Enumerable.Count(other);
if (Count <= otherCount) {
return false;
}
int contains = 0;
int noContains = 0;
foreach (T t in this) {
if (System.Linq.Enumerable.Contains(other, t)) {
contains++;
} else {
noContains++;
}
}
return contains == otherCount && noContains > 0;
}
public bool IsSubsetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in this) {
if (!System.Linq.Enumerable.Contains(other, t)) {
return false;
}
}
return true;
}
public bool IsSupersetOf(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
if (!Contains(t)) {
return false;
}
}
return true;
}
public bool Overlaps(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
if (Contains(t)) {
return true;
}
}
return false;
}
public bool SetEquals(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
int otherCount = System.Linq.Enumerable.Count(other);
if (Count != otherCount) {
return false;
}
return IsSupersetOf(other);
}
public void SymmetricExceptWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
T[] ts = new T[Count];
CopyTo(ts, 0);
HashSet<T> otherList = new HashSet<T>(other);
foreach (T t in ts) {
if (otherList.Contains(t)) {
Remove(t);
otherList.Remove(t);
}
}
foreach (T t in otherList) {
Add(t);
}
}
public void UnionWith(IEnumerable<T> other) {
if (other == null) {
throw new ArgumentNullException("other cannot be null");
}
foreach (T t in other) {
Add(t);
}
}
//
// ICollection<T> implementation
//
public int Count {
get {
return this.dict.Count;
}
}
public bool IsReadOnly {
get {
return this.dict.IsReadOnly;
}
}
void ICollection<T>.Add(T item) {
Add(item);
}
public void Clear() {
this.dict.Clear();
this.list.Clear();
}
public bool Contains(T item) {
return this.dict.ContainsKey(item);
}
public void CopyTo(T[] array, int arrayIndex) {
this.list.CopyTo(array, arrayIndex);
}
public bool Remove(T item) {
LinkedListNode<T> node;
if (!this.dict.TryGetValue(item, out node)) {
return false;
}
this.dict.Remove(item);
this.list.Remove(node);
return true;
}
//
// IEnumerable<T> implementation
//
public IEnumerator<T> GetEnumerator() {
return this.list.GetEnumerator();
}
//
// IEnumerable implementation
//
IEnumerator IEnumerable.GetEnumerator() {
return this.list.GetEnumerator();
}
}
Required usings:
using System;
using System.Collections;
using System.Collections.Generic;
Warning: The class is largely untested, especially the ISet methods. Use at your own risk.
I hope someone finds this useful. :)
There is no direct equivalent in C#. The appropriate class to use depends on the desired behaviour. The HashSet class will preserve the uniqueness of the elements. You may also want to check out SortedSet and SortedDictionary.
There is no class in C# that combines a Linked List with uniqueness required in a Set data structure, so if you need both behaviours then you will need to build your own.
I have briefly implemented a HashSet which guarantees insertion order. It uses the Dictionary to look up items and the LinkedList to preserve order. All three insertion, removal and lookup work still in O(1).
public class OrderedSet<T> : ISet<T>
{
private readonly IDictionary<T, LinkedListNode<T>> m_Dictionary;
private readonly LinkedList<T> m_LinkedList;
public OrderedSet()
{
m_Dictionary = new Dictionary<T, LinkedListNode<T>>();
m_LinkedList = new LinkedList<T>();
}
public bool Add(T item)
{
if (m_Dictionary.ContainsKey(item)) return false;
var node = m_LinkedList.AddLast(item);
m_Dictionary.Add(item, node);
return true;
}
void ICollection<T>.Add(T item)
{
Add(item);
}
public void Clear()
{
m_LinkedList.Clear();
m_Dictionary.Clear();
}
public bool Remove(T item)
{
LinkedListNode<T> node;
bool found = m_Dictionary.TryGetValue(item, out node);
if (!found) return false;
m_Dictionary.Remove(item);
m_LinkedList.Remove(node);
return true;
}
public int Count
{
get { return m_Dictionary.Count; }
}
public IEnumerator<T> GetEnumerator()
{
return m_LinkedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool Contains(T item)
{
return m_Dictionary.ContainsKey(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
m_LinkedList.CopyTo(array, arrayIndex);
}
public virtual bool IsReadOnly
{
get { return m_Dictionary.IsReadOnly; }
}
public void UnionWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public void IntersectWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public void ExceptWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsSubsetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public void SymmetricExceptWith(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsSupersetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsProperSupersetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool IsProperSubsetOf(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool Overlaps(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
public bool SetEquals(IEnumerable<T> other)
{
throw GetNotSupportedDueToSimplification();
}
private static Exception GetNotSupportedDueToSimplification()
{
return new NotSupportedException("This method is not supported due to simplification of example code.");
}
}
Related
it's my first time ever posting on StackOverFlow, because I'm truly desperate right now. I couldn't find an answer for my problem anywhere, so long story short, I have some kind of project for my Data Structures course. The project had 2 parts. The first part was implementing a Sorted Array Bag/ Sorted Collection for some problem. We are using java.
The second part is where I do actually have a lot of problems. So the main idea is implementing a doubly-linked list from the sorted-array bag/ sorted collection and in a way that I would just switch sorted array bag with doubly-linked list in my main and everything should work the way it was working before.
The main thing about the SortedArrayBag is as far as I understand using a Comparator when you declare the SortedArrayBag in your main, and it looks like this:
SortedBag<Grupe> al = new SortedArrayBag<>(new ComparatorVot());
al.add(new Grupe("gr1", 5));
al.add(new Grupe("gr2", 7));
The sorted collection/sorted array bag was implemented by my teacher because there is no such data structure in Java, here is her implementation:
public class SortedArrayBag<T> implements SortedBag<T> {
private ArrayList<T> elemente;
private Comparator<T> relatie;
public SortedArrayBag(Comparator<T> rel) {
this.elemente = new ArrayList<>();
this.relatie = rel;
}
public void add(T elem) {
int index = 0;
boolean added = false;
while (index < this.elemente.size() && added == false) {
T currentElem = this.elemente.get(index);
if (relatie.compare(currentElem, elem) < 0) {
index++;
} else {
this.elemente.add(index, elem);
added = true;
}
}
if (!added) {
this.elemente.add(elem);
}
}
public void remove(T elem) {
boolean removed = this.elemente.remove(elem);
}
public int size() {
return this.elemente.size();
}
public boolean search(T elem) {
return this.elemente.contains(elem);
}
public Iterator<T> iterator() {
return this.elemente.iterator();
}
}
And the SortedBag interface looks like this
public interface SortedBag<T> {
public void add(T elem);
public void remove(T elem);
public int size();
public boolean search(T elem);
public Iterator<T> iterator();
}
Also in case it helps, the comparator looks like this:
public class ComparatorVot implements Comparator<Grupe> {
public int compare(Grupe o1, Grupe o2) {
Grupe gr1 = (Grupe) o1;
Grupe gr2 = (Grupe) o2;
if (gr1.getNrPersoane() / 2 + 1 == gr2.getNrPersoane() / 2 + 1) {
return 0;
} else if (gr1.getNrPersoane() / 2 + 1 > gr2.getNrPersoane() / 2 + 1) {
return 1;
} else {
return -1;
}
}
}
So, I tried my best implementing doublyLinkedList using a SortedArrayBag, this is what I did, also if it helps making my code more clear, prim=first, ultim=last, urmator=next, anterior=previous
import java.util.Iterator;
public class LDI {
private Nod prim;
private Nod ultim;
//private int lungime;
public LDI() {
this.prim = null;
this.ultim = null;
//this.lungime = 0;
}
public class Nod {
private int elem;
private int frecventa;
private Nod urmator;
private Nod anterior;
public Nod(int e, int f) {
this.elem = e;
this.frecventa = f;
this.urmator = null;
this.anterior = null;
}
}
public void add(int elem, int frecventa) {
Nod nodNou = new Nod(elem, frecventa);
nodNou.elem = elem;
nodNou.frecventa = frecventa;
if (prim == null) {
this.prim = nodNou;
this.ultim = nodNou;
} else if (frecventa <= prim.frecventa) {
nodNou.urmator = prim;
this.prim.anterior = nodNou;
this.prim = nodNou;
} else if (frecventa >= prim.frecventa) {
nodNou.anterior = prim;
for (; nodNou.anterior.urmator != null; nodNou.anterior = nodNou.anterior.urmator) {
if (nodNou.anterior.urmator.frecventa > frecventa)
break;
}
nodNou.urmator = nodNou.anterior.urmator;
if (nodNou.anterior.urmator != null) {
nodNou.anterior.urmator.anterior = nodNou;
}
nodNou.anterior.urmator = nodNou;
nodNou.anterior = nodNou.anterior;
}
}
public void remove() {
if (this.prim != null) {
if (this.prim == this.ultim) {
this.prim = null;
this.ultim = null;
} else
this.prim = this.prim.urmator;
this.prim.anterior = null;
}
}
public int size() {
int count = 0;
for (Nod nodNou = prim; nodNou != null; nodNou = nodNou.urmator)
count++;
return count;
}
public class MyIterator {
private Nod curent;
public MyIterator() {
this.curent = prim;
}
public void urmator() {
this.curent = this.curent.urmator;
}
public int getElem() {
return this.curent.elem;
}
public boolean valid() {
if (this.curent != null) {
return true;
} else {
return false;
}
}
}
public Iterator iterator() {
return new MyIterator();
}
}
The thing is, it doesn't work, I have no idea how to make my data structure able to receive the Comparator I used and also the Iterator doesn't work. If you have any idea how to make this work, please do help me.
I want to create a simple Binary Search Tree which uses generics to specify the data type.
However, when I want to create a new tree of Integers, I get the following error:
type argument java.lang.Integer is not within bounds of type-variable T
I tried other data types which are clearly extending Comparable, so why is this not working?
Here is my code:
Interface:
public interface Comparable<T>
{
int compareTo( T t );
}
BinarySearchTree:
public class BinarySearchTree<T extends Comparable<T>>
{
private T content;
private BinarySearchTree<T> leftChild, rightChild;
public BinarySearchTree()
{
content = null;
leftChild = null;
rightChild = null;
}
public T getContent()
{
if(!isEmpty())
{
return content;
}
else
{
throw new RuntimeException();
}
}
public boolean isEmpty()
{
return content == null;
}
public boolean isLeaf()
{
return !isEmpty() && leftChild.isEmpty() && rightChild.isEmpty();
}
public void add(T t)
{
if(isEmpty())
{
content = t;
leftChild = new BinarySearchTree<T>();
rightChild = new BinarySearchTree<T>();
}
else
{
if(content.compareTo(t) > 0)
{
leftChild.add(t);
}
if(content.compareTo(t) < 0)
{
rightChild.add(t);
}
}
}
public int size()
{
if(isEmpty())
{
return 0;
}
else
{
return 1 + leftChild.size() + rightChild.size();
}
}
public boolean contains(T t)
{
if(isEmpty())
{
return false;
}
else
{
if(content.compareTo(t) > 0)
leftChild.contains(t);
else if(content.compareTo(t) < 0)
rightChild.contains(t);
return true;
}
}
public void show()
{
if(!isEmpty())
{
leftChild.show();
System.out.println(content);
rightChild.show();
}
}
}
Main:
public class main
{
public static void main(String[] args)
{
test();
}
public static void test()
{
BinarySearchTree<Integer> tree = new BinarySearchTree<>();
tree.add("5");
tree.add("10");
tree.add("3");
tree.add("1");
tree.show();
}
}
The error comes with this line: BinarySearchTree<Integer> tree = new BinarySearchTree<>();
This is happening because you've defined your own interface Comparable<T>, of which Integer is not a subtype.
Delete your Comparable, and use the one in java.lang instead.
Also, as Eran pointed out, you shouldn't be adding String values to a BinarySearchTree<Integer>.
You should not create your own Comparable interface. It's a part JDK, you can use it.
I defined classes Graph containing GraphNode as follows, my intention for declaring N is to compare 2 GraphNode objects using generics.
The question is how shall I instantiate the Graph which is recursively bound.
error while declaring as below.
Graph<Integer,Comparable<GraphNode>> graph = new Graph<>();
Bound mismatch: The type Comparable<GraphNode> is not a valid substitute for the bounded parameter <N extends Comparable<GraphNode<T,N>>> of the type Graph<T,N>
public class Graph<T, N extends Comparable<GraphNode<T, N>>> {
private N root;
private Class<N> clazz;
Graph(Class<N> clazz) {
this.clazz = clazz;
}
public N getInstance() {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
#SuppressWarnings("unchecked")
public void insert(T d, N n) {
if (root == null && n == null)
root = getInstance();
if (root == null)
root = n;
N node = root;
while (node != null) {
if (node.equals(n)) {
N newNode = getInstance();
((GraphNode<T, N>) newNode).setAdjNode(newNode);
}
}
}
}
public class GraphNode<T, N extends Comparable<GraphNode<T, N>>> implements Comparable<N> {
private T data;
private LinkedHashSet<N> adjNodes = new LinkedHashSet<>();
GraphNode() {
data = null;
}
GraphNode(T d) {
setData(d);
}
public void setAdjNode(N n) {
adjNodes.add(n);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
#Override
public int hashCode() {
return data.hashCode();
}
#Override
public boolean equals(Object obj) {
if (obj instanceof GraphNode<?, ?>) {
return ((GraphNode<?, ?>) obj).getData() == this.getData();
}
return false;
}
#Override
public String toString() {
return data + "";
}
#Override
public int compareTo(N o) {
return this.compareTo(o);
}
}
This solved my above problem
public class Graph<T extends Comparable<T>> {
private GraphNode<T> root;
public void insert(T d, GraphNode<T> n) {
if (root == null && n == null)
root = new GraphNode<T>(d);
if (root == null)
root = n;
GraphNode<T> node = root;
Queue<GraphNode<T>> queue = new ConcurrentLinkedQueue<>();
queue.add(root);
while (!queue.isEmpty()) {
node = queue.poll();
node.setNodeColor(color.BLACK);
if (node.equals(n)) {
GraphNode<T> newNode = new GraphNode<T>(d);
((GraphNode<T>) newNode).setAdjNode(newNode);
} else {
queue.addAll(node.getUnexploredAdjNodes());
}
}
}
}
public class GraphNode<T extends Comparable<T>> implements Comparable<GraphNode<T>> {
enum color {
WHITE, GREY, BLACK
};
private T data;
private color nodeColor = color.WHITE;
private LinkedHashSet<GraphNode<T>> adjNodes = new LinkedHashSet<>();
GraphNode() {
data = null;
}
GraphNode(T d) {
setData(d);
}
public void setAdjNode(GraphNode<T> n) {
adjNodes.add(n);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public LinkedHashSet<GraphNode<T>> getAdjNodes() {
return adjNodes;
}
public LinkedHashSet<GraphNode<T>> getUnexploredAdjNodes() {
LinkedHashSet<GraphNode<T>> n = new LinkedHashSet<>();
for (GraphNode<T> node : adjNodes) {
if (node.getNodeColor() == color.WHITE)
n.add(node);
}
return n;
}
public color getNodeColor() {
return nodeColor;
}
public void setNodeColor(color nodeColor) {
this.nodeColor = nodeColor;
}
#Override
public int hashCode() {
return data.hashCode();
}
#Override
public boolean equals(Object obj) {
if (obj instanceof GraphNode<?>) {
return ((GraphNode<?>) obj).getData() == this.getData();
}
return false;
}
#Override
public int compareTo(GraphNode<T> o) {
return data.compareTo(o.data);
}
#Override
public String toString() {
return data + "";
}
}
Graph<Integer> graph = new Graph<>();
So I've been tasked to create a method to remove an element from a MultiSet. I've been trying for a while, but sadly in vain. My code is as follows:
import java.util.*;
public class MultiSet<E> extends AbstractCollection<E> {
private HashMap<E, Integer> elements;
private int noOfElems;
public MultiSet() {
elements = new HashMap<E, Integer>();
noOfElems= 0;
}
public MultiSet(Collection<E> c) {
this();
addAll(c);
}
public int size() {
return noOfElems;
}
public Iterator<E> iterator() {
return new Iterator<E>() {
Iterator<E> iterator = elements.keySet().iterator();
int elemsLeft = 0;
E thisElem = null;
public boolean hasNext() {
return iterator.hasNext();
}
public E next() {
if (elemsLeft == 0) {
thisElem = iterator.next();
elemsLeft = elements.get(thisElem);
}
elemsLeft -= elemsLeft;
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public boolean add(E e) {
Integer i = elements.get(e);
if(i == null) {
i = 1;
} else {
i += 1;
}
elements.put(e, i);
noOfElems++;
return true;
}
public String toString() {
return elements.toString();
}
public int hashCode() {
return elements.hashCode();
}
public boolean equals(MultiSet<E> other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (this.getClass() != other.getClass()) {
return false;
}
MultiSet<?> obj = (MultiSet<?>) other;
return obj.elements.equals(elements);
}
public boolean remove(Object o) {
}
}
And I want to implement the remove method. Anything that will help me, even a few pointers on where to start, will be greatly appreciated. Thanks! (also, comments on the rest of my code will also be appreciated)
This multiset just stores the elements as hash keys mapped to a count of the number of occurrences. To remove all instances of an element, just delete the key:
public void remove_all(E e) {
elements.remove(e);
}
If you need to remove only one instance, then decrement the count unless it's already a 1. In that case, remove the key.
public void remove(E e) {
Integer i = elements.get(e);
if (i != null) {
if (i == 1) {
elements.remove(e);
} else {
elements.put(e, i - 1);
}
}
}
BTW it's a bit hard to believe this is your code. If you understand enough to write the methods you've already written, how could you not know even where to start on remove?
I'm quite new to Java so this is probably pretty straight forward question.
I want to sort an ArrayList in the class MediaLib based on the natural order of a specified key.
I can't 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
}
}
}
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));
}