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?
Related
I need to create a vector class that implements the Map interface, but in the put method it returns NullException, I need help implementing the put method, I can't find this type of content on the internet
public class Vetor_map implements Map<Key, Student> {
private int nElements;
private Map<Key, Student> mapa[];
public Vetor_map(int max) {
mapa = new Map[max];
nElements = 0;
}
// PUT
#Override
public Estudante put(Key key, Estudants value) {
if (!isFull()) {
mapa[nElements].put(key, value);
nElements++;
return value;
}
return value;
}
public boolean isEmpty() {
// TODO Auto-generated method stub
if (nElements == 0)
return true;
return false;
}
public boolean isFull() {
if (nElements == mapa.length) {
return true;
}
return false;
}
Class main:
public static void main(String[] args) {
// TODO Auto-generated method stub
Key ch = new Key();
Student es = new Student();
Vetor_map vm = new Vetor_map(10);
System.out.println("Key: " + ch + ", Estudant: "+ es);
vm.put(ch, es);
Error
A Map is a collection of entries where each entry is a key-value pair. So your Vetor_map class should implement java.util.Map – which it does – but I think that you should also create a class that implements interface Map.Entry.
In the below code, I added an inner class VectorMapEntry that implements Map.Entry and therefore class VectorMap – which implements interface Map – contains an array of VectorMapEntry instances. From there it is just a simple matter of implementing the methods of both interfaces, namely Map and Map.Entry.
Note the following in the below code.
I changed the name from Vetor_map to VectorMap.
I added methods toString() and main() to class VectorMap for testing purposes only. I also added method toString() to classes Key and Student also for testing purposes.
You did not supply code for classes Key and Student so I added skeleton definitions for those two classes. Note that each class – Key and Student – must each implement method equals. I only added method hashCode since the javadoc for method equals() recommends doing so.
VectorMap cannot contain a null Key but it can contain a null Student as a value for a given Key.
Each Key in VectorMap is unique. When calling method put() with a Key that already exists in VectorMap, the existing value is replaced.
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class VectorMap implements Map<Key, Student> {
private static class VectorMapEntry implements Map.Entry<Key, Student> {
private Key key;
private Student student;
public VectorMapEntry(Key k, Student s) {
key = k;
student = s;
}
public Key getKey() {
return key;
}
public Student getStudent() {
return student;
}
public void setStudent(Student s) {
student = s;
}
#Override
public Student getValue() {
return student;
}
#Override
public Student setValue(Student value) {
student = value;
return value;
}
}
private int nElements;
private VectorMapEntry[] entries;
public VectorMap(int initialSize) {
if (initialSize <= 0) {
throw new IllegalArgumentException("Initial size must be positive.");
}
entries = new VectorMapEntry[initialSize];
}
#Override
public int size() {
return nElements;
}
#Override
public boolean isEmpty() {
return nElements == 0;
}
#Override
public boolean containsKey(Object key) {
boolean found = false;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
found = entry.getKey().equals(key);
if (found) {
break;
}
}
return found;
}
#Override
public boolean containsValue(Object value) {
boolean found = false;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
found = entry.getStudent().equals(value);
if (found) {
break;
}
}
return found;
}
#Override
public Student get(Object key) {
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
if (entry.getKey().equals(key)) {
return entry.getStudent();
}
}
return null;
}
#Override
public Student put(Key key, Student value) {
if (key == null) {
throw new IllegalArgumentException("Null key.");
}
boolean found = false;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
if (entry.getKey().equals(key)) {
entry.setStudent(value);
found = true;
break;
}
}
if (!found) {
if (nElements == entries.length) {
throw new RuntimeException("Map is full.");
}
entries[nElements] = new VectorMapEntry(key, value);
nElements++;
}
return value;
}
#Override
public Student remove(Object key) {
int index = 0;
Student s = null;
for (VectorMapEntry entry : entries) {
if (entry == null) {
break;
}
if (entry.getKey().equals(key)) {
s = entry.getStudent();
break;
}
index++;
}
if (index < nElements) {
for (int i = index; i < nElements - 1; i++) {
entries[i] = entries[i + 1];
}
nElements--;
}
return s;
}
#Override
public void putAll(Map<? extends Key, ? extends Student> m) {
if (m != null) {
m.entrySet()
.stream()
.forEach(ent -> put(ent.getKey(), ent.getValue()));
}
}
#Override
public void clear() {
for (int i = 0; i < nElements; i++) {
entries[i] = null;
}
nElements = 0;
}
#Override
public Set<Key> keySet() {
Set<Key> keySet = new HashSet<>();
for (int i = 0; i < nElements; i++) {
keySet.add(entries[i].getKey());
}
return keySet;
}
#Override
public Collection<Student> values() {
Collection<Student> vals = new ArrayList<>(nElements);
for (int i = 0; i < nElements; i++) {
vals.add(entries[i].getStudent());
}
return vals;
}
#Override
public Set<Map.Entry<Key, Student>> entrySet() {
Set<Map.Entry<Key, Student>> entSet = new HashSet<>();
for (int i = 0; i < nElements; i++) {
entSet.add(entries[i]);
}
return entSet;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
boolean first = true;
for (int i = 0; i < nElements; i++) {
if (first) {
first = false;
}
else {
sb.append(", ");
}
sb.append(entries[i].getKey());
sb.append('=');
sb.append(entries[i].getValue());
}
sb.append(']');
return sb.toString();
}
public static void main(String[] args) {
Key ch = new Key();
Student es = new Student();
VectorMap vm = new VectorMap(10);
System.out.println("Key: " + ch + ", Estudant: "+ es);
vm.put(ch, es);
System.out.println(vm);
}
}
class Key {
public boolean equals(Object obj) {
return false;
}
public int hashCode() {
return -1;
}
public String toString() {
return "Key";
}
}
class Student {
public boolean equals(Object obj) {
return false;
}
public int hashCode() {
return -1;
}
public String toString() {
return "Student";
}
}
Also note that it would be possible to change the above code such that VectorMap could (theoretically) contain an infinite number of key-value pairs. This could be achieved by simply enlarging the entries array whenever it gets completely filled.
Hi,
Update: Thanks for all your suggestion
assuming that, this exercise it's like a rebus,
I have a list of numbers made with the concept of Cons and Nil,
List l = new Cons(**3**, new Cons(**2**,new Cons(**1**, new
Cons(**4**, new Cons(**1**, new Nil())))));
and I want to count how many of them are immediately followed by a lower number, recursively.
For example
[5,0,5,3].count() == 2, [5,5,0].count() == 1
The count() method is made by me (it cannot have any parameters), the rest is default, and I can't make and other method or use already defined one's like add(),size()...
The "NEXT" must have the next value after the current elem but I can't get a solution.
Any solutions are welcome.
abstract class List {
public abstract boolean empty();
public abstract int first();
public abstract int count();
}
class Cons extends List {
private int elem;
private List next;
public Cons(int elem, List next) {
this.elem = elem;
this.next = next;
}
public boolean empty(){
return false;
}
public int first(){
return elem;
}
#Override
public int count() {
if(elem>NEXT) {
return 1 + next.count();
}else {
return next.count();
}
}
```![enter image description here](https://i.stack.imgur.com/kWo0v.jpg)
The following code will create a recursive list with N elements with N value being defined by the size of the amount of elements found in the int array called elements in RecursiveList class. Call the startRecursion() method to create a recursive list with the defined elements and call count() to get the amount of elements in the array that are immediately followed by a lower number.
Main Class
This your application entry point:
public static void main(String[] args) {
int count = RecursiveList.startRecursion().count();
System.out.printf("List has %d recursive elements", count);
}
RecursiveList Class
abstract class RecursiveList {
protected static int index = -1;
protected static int[] elements = new int[]{ 5,2,1,4,3,2,6 };
public static RecursiveList startRecursion() {
return new Cons();
}
public abstract boolean empty();
public abstract int count();
public abstract Integer getElement();
public static int incIndex() {
return index += 1;
}
}
Cons Class
public class Cons extends RecursiveList {
private static int result;
private final Integer elem;
private final RecursiveList prev;
private final RecursiveList next;
private Cons(Cons parent) {
prev = parent;
elem = incIndex() < elements.length ? elements[index] : null;
System.out.printf("Creating new Cons with element %d(%d)%n", elem, index);
next = elem != null ? new Cons(this) : null;
}
Cons() {
this(null);
}
public boolean empty() {
return false;
}
#Override
public /*#Nullable*/ Integer getElement() {
return elem;
}
#Override
public int count() {
if (elem != null)
{
if (prev != null && elem < prev.getElement())
result += 1;
if (next != null) {
return next.count();
}
}
return result;
}
}
EDIT
Alright here is the answer you were actually looking for. This completely conforms to the limitations imposed on this exercise that you provided. The solution uses pure Java, neither the class nor any of it's method or field declarations were modified in any way and no such new elements were added. I've only added the implementation where the exercise said you should.
Main Class
public static void main(String[] args) {
List l = new Cons(3, new Cons(2,new Cons(1, new
Cons(4, new Cons(1, new Nil())))));
assert l.count() == 3;
l = new Cons(5, new Nil());
assert l.count() == 0;
l = new Cons(5, new Cons(5, new Cons(0, new Nil())));
assert l.count() == 1;
l = new Cons(5, new Cons(0, new Cons(5, new Cons(3, new Nil()))));
assert l.count() == 2;
System.out.println("All tests completed successfully!");
}
Cons Class
import java.util.NoSuchElementException;
public class Cons extends List {
private int elem;
private List next;
public Cons(int elem, List next) {
this.elem = elem;
this.next = next;
}
public boolean empty()
{ return false; }
public int first()
{ return elem; }
public int count()
{
try {
if (first() > next.first()) {
return 1 + next.count();
}
else return next.count();
}
catch (NoSuchElementException e) {
return 0;
}
}
}
Nil Class
import java.util.NoSuchElementException;
public class Nil extends List {
public boolean empty()
{ return true; }
public int first()
{ throw new NoSuchElementException(); }
public int count()
{
throw new IllegalAccessError();
}
}
public int NEXT(){
if(next!=null)
return next.first()
else
throw new Exception("No next element")
}
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.
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.");
}
}