Skip to content

Commit 6bd6f43

Browse files
author
alxkm
committed
refactor: Bag data structure
1 parent 7c58b19 commit 6bd6f43

File tree

2 files changed

+155
-60
lines changed
  • src
    • main/java/com/thealgorithms/datastructures/bags
    • test/java/com/thealgorithms/datastructures/bag

2 files changed

+155
-60
lines changed

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

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,68 @@
44
import java.util.NoSuchElementException;
55

66
/**
7-
* Collection which does not allow removing elements (only collect and iterate)
7+
* A collection that allows adding and iterating over elements but does not support element removal.
88
*
9-
* @param <Element> - the generic type of an element in this bag
9+
* @param <E> the type of elements in this bag
1010
*/
11-
public class Bag<Element> implements Iterable<Element> {
11+
public class Bag<E> implements Iterable<E> {
1212

13-
private Node<Element> firstElement; // first element of the bag
14-
private int size; // size of bag
13+
private Node<E> firstElement; // First element in the bag
14+
private int size; // Number of elements in the bag
1515

16-
private static final class Node<Element> {
17-
18-
private Element content;
19-
private Node<Element> nextElement;
16+
// Node class representing each element in the bag
17+
private static final class Node<E> {
18+
private E content;
19+
private Node<E> nextElement;
2020
}
2121

2222
/**
23-
* Create an empty bag
23+
* Constructs an empty bag.
2424
*/
2525
public Bag() {
2626
firstElement = null;
2727
size = 0;
2828
}
2929

3030
/**
31-
* @return true if this bag is empty, false otherwise
31+
* Checks if the bag is empty.
32+
*
33+
* @return true if the bag is empty, false otherwise
3234
*/
3335
public boolean isEmpty() {
34-
return firstElement == null;
36+
return size == 0;
3537
}
3638

3739
/**
40+
* Returns the number of elements in the bag.
41+
*
3842
* @return the number of elements
3943
*/
4044
public int size() {
4145
return size;
4246
}
4347

4448
/**
45-
* @param element - the element to add
49+
* Adds an element to the bag.
50+
*
51+
* @param element the element to add
4652
*/
47-
public void add(Element element) {
48-
Node<Element> oldfirst = firstElement;
49-
firstElement = new Node<>();
50-
firstElement.content = element;
51-
firstElement.nextElement = oldfirst;
53+
public void add(E element) {
54+
Node<E> newNode = new Node<>();
55+
newNode.content = element;
56+
newNode.nextElement = firstElement;
57+
firstElement = newNode;
5258
size++;
5359
}
5460

5561
/**
56-
* Checks if the bag contains a specific element
62+
* Checks if the bag contains a specific element.
5763
*
58-
* @param element which you want to look for
59-
* @return true if bag contains element, otherwise false
64+
* @param element the element to check for
65+
* @return true if the bag contains the element, false otherwise
6066
*/
61-
public boolean contains(Element element) {
62-
for (Element value : this) {
67+
public boolean contains(E element) {
68+
for (E value : this) {
6369
if (value.equals(element)) {
6470
return true;
6571
}
@@ -68,61 +74,37 @@ public boolean contains(Element element) {
6874
}
6975

7076
/**
71-
* @return an iterator that iterates over the elements in this bag in
72-
* arbitrary order
77+
* Returns an iterator over the elements in this bag.
78+
*
79+
* @return an iterator that iterates over the elements in the bag
7380
*/
74-
public Iterator<Element> iterator() {
81+
@Override
82+
public Iterator<E> iterator() {
7583
return new ListIterator<>(firstElement);
7684
}
7785

78-
@SuppressWarnings("hiding")
79-
private class ListIterator<Element> implements Iterator<Element> {
86+
// Private class for iterating over elements
87+
private static class ListIterator<E> implements Iterator<E> {
8088

81-
private Node<Element> currentElement;
89+
private Node<E> currentElement;
8290

83-
ListIterator(Node<Element> firstElement) {
84-
currentElement = firstElement;
91+
ListIterator(Node<E> firstElement) {
92+
this.currentElement = firstElement;
8593
}
8694

95+
@Override
8796
public boolean hasNext() {
8897
return currentElement != null;
8998
}
9099

91-
/**
92-
* remove is not allowed in a bag
93-
*/
94100
@Override
95-
public void remove() {
96-
throw new UnsupportedOperationException();
97-
}
98-
99-
public Element next() {
101+
public E next() {
100102
if (!hasNext()) {
101103
throw new NoSuchElementException();
102104
}
103-
Element element = currentElement.content;
105+
E element = currentElement.content;
104106
currentElement = currentElement.nextElement;
105107
return element;
106108
}
107109
}
108-
109-
/**
110-
* main-method for testing
111-
*/
112-
public static void main(String[] args) {
113-
Bag<String> bag = new Bag<>();
114-
115-
bag.add("1");
116-
bag.add("1");
117-
bag.add("2");
118-
119-
System.out.println("size of bag = " + bag.size());
120-
for (String s : bag) {
121-
System.out.println(s);
122-
}
123-
124-
System.out.println(bag.contains(null));
125-
System.out.println(bag.contains("1"));
126-
System.out.println(bag.contains("3"));
127-
}
128110
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package com.thealgorithms.datastructures.bag;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
6+
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
import static org.junit.jupiter.api.Assertions.fail;
8+
9+
import com.thealgorithms.datastructures.bags.Bag;
10+
import org.junit.jupiter.api.Test;
11+
import java.util.Iterator;
12+
13+
class BagTest {
14+
15+
@Test
16+
void testBagOperations() {
17+
Bag<String> bag = new Bag<>();
18+
assertTrue(bag.isEmpty(), "Bag should be empty initially");
19+
assertEquals(0, bag.size(), "Bag size should be 0 initially");
20+
21+
bag.add("item1");
22+
bag.add("item2");
23+
bag.add("item1"); // adding duplicate item
24+
25+
assertFalse(bag.isEmpty(), "Bag should not be empty after adding elements");
26+
assertEquals(3, bag.size(), "Bag size should be 3 after adding 3 elements");
27+
28+
assertTrue(bag.contains("item1"), "Bag should contain 'item1'");
29+
assertTrue(bag.contains("item2"), "Bag should contain 'item2'");
30+
assertFalse(bag.contains("item3"), "Bag should not contain 'item3'");
31+
assertFalse(bag.contains(null), "Bag should not contain null");
32+
33+
// Test iteration
34+
int count = 0;
35+
for (String item : bag) {
36+
assertTrue(item.equals("item1") || item.equals("item2"), "Item should be either 'item1' or 'item2'");
37+
count++;
38+
}
39+
assertEquals(3, count, "Iterator should traverse all 3 items");
40+
}
41+
42+
@Test
43+
void testBagInitialization() {
44+
Bag<String> bag = new Bag<>();
45+
assertTrue(bag.isEmpty(), "Bag should be empty initially");
46+
assertEquals(0, bag.size(), "Bag size should be 0 initially");
47+
}
48+
49+
@Test
50+
void testAddElements() {
51+
Bag<String> bag = new Bag<>();
52+
bag.add("item1");
53+
bag.add("item2");
54+
bag.add("item1"); // Adding duplicate item
55+
56+
assertFalse(bag.isEmpty(), "Bag should not be empty after adding elements");
57+
assertEquals(3, bag.size(), "Bag size should be 3 after adding 3 elements");
58+
}
59+
60+
@Test
61+
void testContainsMethod() {
62+
Bag<String> bag = new Bag<>();
63+
bag.add("item1");
64+
bag.add("item2");
65+
66+
assertTrue(bag.contains("item1"), "Bag should contain 'item1'");
67+
assertTrue(bag.contains("item2"), "Bag should contain 'item2'");
68+
assertFalse(bag.contains("item3"), "Bag should not contain 'item3'");
69+
assertFalse(bag.contains(null), "Bag should not contain null");
70+
}
71+
72+
@Test
73+
void testContainsAfterRemoveOperation() {
74+
Bag<String> bag = new Bag<>();
75+
bag.add("item1");
76+
bag.add("item2");
77+
assertTrue(bag.contains("item1"), "Bag should contain 'item1' before removal");
78+
assertTrue(bag.contains("item2"), "Bag should contain 'item2' before removal");
79+
}
80+
81+
@Test
82+
void testIterator() {
83+
Bag<String> bag = new Bag<>();
84+
bag.add("item1");
85+
bag.add("item2");
86+
bag.add("item3");
87+
88+
int count = 0;
89+
for (String item : bag) {
90+
assertTrue(item.equals("item1") || item.equals("item2") || item.equals("item3"), "Item should be one of 'item1', 'item2', or 'item3'");
91+
count++;
92+
}
93+
assertEquals(3, count, "Iterator should traverse all 3 items");
94+
}
95+
96+
@Test
97+
void testIteratorEmptyBag() {
98+
Bag<String> bag = new Bag<>();
99+
int count = 0;
100+
for (String ignored : bag) {
101+
fail("Iterator should not return any items for an empty bag");
102+
}
103+
assertEquals(0, count, "Iterator should not traverse any items in an empty bag");
104+
}
105+
106+
@Test
107+
void testRemoveMethodThrowsException() {
108+
Bag<String> bag = new Bag<>();
109+
bag.add("item1");
110+
Iterator<String> iterator = bag.iterator();
111+
assertThrows(UnsupportedOperationException.class, iterator::remove, "Remove operation should throw UnsupportedOperationException");
112+
}
113+
}

0 commit comments

Comments
 (0)