Skip to content

Commit 8c72c87

Browse files
committed
refactor: Enhance docs, add more tests in Bag
1 parent 7bbdae5 commit 8c72c87

File tree

2 files changed

+89
-13
lines changed
  • src
    • main/java/com/thealgorithms/datastructures/bags
    • test/java/com/thealgorithms/datastructures/bag

2 files changed

+89
-13
lines changed

src/main/java/com/thealgorithms/datastructures/bags/Bag.java

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
import java.util.NoSuchElementException;
55

66
/**
7-
* A collection that allows adding and iterating over elements but does not support element removal.
7+
* A generic collection that allows adding and iterating over elements but does not support
8+
* element removal. This class implements a simple bag data structure, which can hold duplicate
9+
* elements and provides operations to check for membership and the size of the collection.
10+
*
11+
* <p>Bag is not thread-safe and should not be accessed by multiple threads concurrently.
812
*
913
* @param <E> the type of elements in this bag
1014
*/
1115
public class Bag<E> implements Iterable<E> {
1216

13-
private Node<E> firstElement; // First element in the bag
14-
private int size; // Number of elements in the bag
17+
private Node<E> firstElement; // Reference to the first element in the bag
18+
private int size; // Count of elements in the bag
1519

1620
// Node class representing each element in the bag
1721
private static final class Node<E> {
@@ -21,6 +25,7 @@ private static final class Node<E> {
2125

2226
/**
2327
* Constructs an empty bag.
28+
* <p>This initializes the bag with zero elements.
2429
*/
2530
public Bag() {
2631
firstElement = null;
@@ -30,7 +35,7 @@ public Bag() {
3035
/**
3136
* Checks if the bag is empty.
3237
*
33-
* @return true if the bag is empty, false otherwise
38+
* @return {@code true} if the bag contains no elements; {@code false} otherwise
3439
*/
3540
public boolean isEmpty() {
3641
return size == 0;
@@ -39,7 +44,7 @@ public boolean isEmpty() {
3944
/**
4045
* Returns the number of elements in the bag.
4146
*
42-
* @return the number of elements
47+
* @return the number of elements currently in the bag
4348
*/
4449
public int size() {
4550
return size;
@@ -48,7 +53,10 @@ public int size() {
4853
/**
4954
* Adds an element to the bag.
5055
*
51-
* @param element the element to add
56+
* <p>This method adds the specified element to the bag. Duplicates are allowed, and the
57+
* bag will maintain the order in which elements are added.
58+
*
59+
* @param element the element to add; must not be {@code null}
5260
*/
5361
public void add(E element) {
5462
Node<E> newNode = new Node<>();
@@ -61,8 +69,10 @@ public void add(E element) {
6169
/**
6270
* Checks if the bag contains a specific element.
6371
*
64-
* @param element the element to check for
65-
* @return true if the bag contains the element, false otherwise
72+
* <p>This method uses the {@code equals} method of the element to determine membership.
73+
*
74+
* @param element the element to check for; must not be {@code null}
75+
* @return {@code true} if the bag contains the specified element; {@code false} otherwise
6676
*/
6777
public boolean contains(E element) {
6878
for (E value : this) {
@@ -76,6 +86,8 @@ public boolean contains(E element) {
7686
/**
7787
* Returns an iterator over the elements in this bag.
7888
*
89+
* <p>The iterator provides a way to traverse the elements in the order they were added.
90+
*
7991
* @return an iterator that iterates over the elements in the bag
8092
*/
8193
@Override
@@ -88,19 +100,35 @@ private static class ListIterator<E> implements Iterator<E> {
88100

89101
private Node<E> currentElement;
90102

103+
/**
104+
* Constructs a ListIterator starting from the given first element.
105+
*
106+
* @param firstElement the first element of the bag to iterate over
107+
*/
91108
ListIterator(Node<E> firstElement) {
92109
this.currentElement = firstElement;
93110
}
94111

112+
/**
113+
* Checks if there are more elements to iterate over.
114+
*
115+
* @return {@code true} if there are more elements; {@code false} otherwise
116+
*/
95117
@Override
96118
public boolean hasNext() {
97119
return currentElement != null;
98120
}
99121

122+
/**
123+
* Returns the next element in the iteration.
124+
*
125+
* @return the next element in the bag
126+
* @throws NoSuchElementException if there are no more elements to return
127+
*/
100128
@Override
101129
public E next() {
102130
if (!hasNext()) {
103-
throw new NoSuchElementException();
131+
throw new NoSuchElementException("No more elements in the bag.");
104132
}
105133
E element = currentElement.content;
106134
currentElement = currentElement.nextElement;

src/test/java/com/thealgorithms/datastructures/bag/BagTest.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
44
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
56
import static org.junit.jupiter.api.Assertions.assertTrue;
67

78
import com.thealgorithms.datastructures.bags.Bag;
@@ -68,12 +69,12 @@ void testContainsMethod() {
6869
}
6970

7071
@Test
71-
void testContainsAfterRemoveOperation() {
72+
void testContainsAfterAdditions() {
7273
Bag<String> bag = new Bag<>();
7374
bag.add("item1");
7475
bag.add("item2");
75-
assertTrue(bag.contains("item1"), "Bag should contain 'item1' before removal");
76-
assertTrue(bag.contains("item2"), "Bag should contain 'item2' before removal");
76+
assertTrue(bag.contains("item1"), "Bag should contain 'item1' after addition");
77+
assertTrue(bag.contains("item2"), "Bag should contain 'item2' after addition");
7778
}
7879

7980
@Test
@@ -106,6 +107,53 @@ void testRemoveMethodThrowsException() {
106107
Bag<String> bag = new Bag<>();
107108
bag.add("item1");
108109
Iterator<String> iterator = bag.iterator();
109-
org.junit.jupiter.api.Assertions.assertThrows(UnsupportedOperationException.class, iterator::remove, "Remove operation should throw UnsupportedOperationException");
110+
assertThrows(UnsupportedOperationException.class, iterator::remove, "Remove operation should throw UnsupportedOperationException");
111+
}
112+
113+
@Test
114+
void testMultipleDuplicates() {
115+
Bag<String> bag = new Bag<>();
116+
bag.add("item1");
117+
bag.add("item1");
118+
bag.add("item1"); // Add three duplicates
119+
120+
assertEquals(3, bag.size(), "Bag size should be 3 after adding three duplicates");
121+
assertTrue(bag.contains("item1"), "Bag should contain 'item1'");
122+
}
123+
124+
@Test
125+
void testLargeNumberOfElements() {
126+
Bag<Integer> bag = new Bag<>();
127+
for (int i = 0; i < 1000; i++) {
128+
bag.add(i);
129+
}
130+
assertEquals(1000, bag.size(), "Bag should contain 1000 elements");
131+
}
132+
133+
@Test
134+
void testMixedTypeElements() {
135+
Bag<Object> bag = new Bag<>();
136+
bag.add("string");
137+
bag.add(1);
138+
bag.add(2.0);
139+
140+
assertTrue(bag.contains("string"), "Bag should contain a string");
141+
assertTrue(bag.contains(1), "Bag should contain an integer");
142+
assertTrue(bag.contains(2.0), "Bag should contain a double");
143+
}
144+
145+
@Test
146+
void testIteratorWithDuplicates() {
147+
Bag<String> bag = new Bag<>();
148+
bag.add("item1");
149+
bag.add("item1");
150+
bag.add("item2");
151+
152+
int count = 0;
153+
for (String item : bag) {
154+
assertTrue(item.equals("item1") || item.equals("item2"), "Item should be either 'item1' or 'item2'");
155+
count++;
156+
}
157+
assertEquals(3, count, "Iterator should traverse all 3 items including duplicates");
110158
}
111159
}

0 commit comments

Comments
 (0)