Nhu Nguyen 6 лет назад
Родитель
Сommit
9f9c61cf1e

+ 18
- 76
README.md Просмотреть файл

@@ -1,93 +1,35 @@
1 1
 # Store Lab
2 2
 * **Purpose** - to understand [HashMap](https://www.youtube.com/watch?v=shs0KM3wKv8), [objects](https://docs.oracle.com/javase/tutorial/java/concepts/object.html) and [data encapsulation](https://en.wikipedia.org/wiki/Data_encapsulation).
3 3
 
4
-* **Objective** - to create two type of maps
4
+* **Objective** - A map/associative array is a data type that allow users to search for a value. The objective of this lab is to understand how to create map and see how we store data affects how its performance.
5
+
5 6
 
6 7
 ## Part 1 - Equals & HashCode
7
-By default, every [Java object](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html) has an [equals](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals) and a [hashCode](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode) method. Java uses the object's address to calculate the [hashCode](https://en.wikipedia.org/wiki/Hash_function). By default, two objects are equal if they have the same address. We don't want this. Two objects are equal if they are the same class and have the same values.
8
+By default, every [Java object](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html) has an [equals](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals) and a [hashCode](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode) method. Java uses the object's address to calculate the [hashCode](https://en.wikipedia.org/wiki/Hash_function). By default, two objects are equal if they have the same address. We don't want this. Two objects are equal if they are the same class and have the same values. Your task is to add the `equals` and `hashCode` to the `User` and `Cart` class.
8 9
 
9 10
   1. User
10
-    1. Add an `equals` method to the `User` class. The equal method should return true only if the `id` and `name` of the user are the same. It return false otherwise.
11
+    1. Add an `equals` method to the `User` class. The equal method should return true only if the `id` and `name` are the same. It return false otherwise.
11 12
     2. Add a `hashCode` method by calling `Objects.hash()` and gives it the `id` and `name` (e.g. `Objects.hash(id, name)`)
12 13
   2. Cart
13 14
     1. Add an `equals` and `hashCode` methods with IntelliJ shortcut
14 15
       1. Click `Command + N` and select `equals and hashCode`. Follow the wizard to generate the code.
15 16
 
16
-## Part 2 - ListMap
17
-
18
-
19
-
20
-
21
-This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language
22
-
23
-
24
-## Part 1 - ListMap
25
-In the `test` folder, there is a `ProductTest` with most of the tested commented out.
26
-  1. The first test `testConstruction_WithNoParams` checks to see if the `Product` class has an empty constructor. To test it, I created a new object with no parameter.
27
-  2. The second test `testGetSetName` checks to see if you can set and get the name of the product. In order to make this pass, I added a `String` field called `name` (line 5). Then I added a getter method `getName` (line 18-20) and a setter method `setName(String name)` (line 23-25).
28
-  3. The third test `testConstruction_WithName` checks if the `Product` class has a constructor that takes a String. Notice we can have more than one constructor. When I create a new Product with a string `new Product("T-shirt")`, I set that string to the field `name` so when I called `getName`, I get the string that I passed into the constructor.
29
-  4. Continue to uncomment the test and write the code to make it pass
30
-  5. For the product description, it should be in this format `title (Color: color, Size: size)`
31
-    - ex: `Hat (Color: Yellow, Size: LG)`
32
-
33
-## Part 2 - Cart
34
-A cart has an array of Product.
35
-  1. Open the `CartTest` and uncomment line 9-13. To make the test pass:
36
-    - Create a new class named `Cart`
37
-    - Create a new constructor that takes an array of Product
38
-    - Run the test, it should pass
39
-  2. Create a getter for Product to make `testGetProducts` test pass
40
-  3. To make `testGetSetDiscount` test pass:
41
-    - Create a new decimal field called `discount`
42
-    - Create a getter and setter for the field
43
-    - Run the test
44
-  4. To get `getProductTotal` tests to pass, you need add all the product prices together and return the result.
45
-  5. To get the total, you need to add the total of all the products minus the discount. For example, if a product costs $100, and the discount is 20% (0.20), then the total = 100 - (100 * 0.20) = 80
46
-
47
-## Part 3 - CreditCard
48
-The goal of this exercise is to know how to create and test a class.
49
-  1. In the test folder, create a new test class called `CreditCardTest`
50
-  2. Create a new class called `CreditCard`
51
-  2. Create a test case to get and set the `cardHolderName` of the type `String`
52
-      - Create getter and setter methods in the `CreditCard` class
53
-      - Add a field called cardHolderName
54
-  2. Do the same for the following fields:
55
-    - `String number`
56
-    - `int expiredMonth`
57
-    - `int expiredYear`
58
-  3. Create a getter and setter for each field
59
-  4. Create a test for `getDescription`
60
-    - `getDescription` should return `[cardHolderName] [last 4 digit of the number] [expiredMonth]/[expiredYear]`
61
-      - ex: `Tia Mowry 4551 10/2019`
62
-  5. Add a `CreditCard` field to the `Cart` class
63
-    - Add a getter and setter for the `creditCard` field
17
+## Map
18
+Details instructions on what each method should do and return is in `MyMap` class.
64 19
 
65
-## Part 4 - Product as an ArrayList - BONUS
66
-The goal of this exercise is to change the `products` array in the `Cart` class to an ArrayList.
67
-  1. In the `CartTest`, change the `products` array to an `ArrayList`
20
+### Part 2 - ListMap
21
+A list map stores every entry in a list. Every time the user calls `put`, create a new `Entry` and add it to the list. Your task is to make all the test pass.
22
+  1. Uncomment line 178 - 196. Notice how long the test takes to run.
68 23
 
69
-    ```java
70
-      ArrayList<Product> products = new ArrayList();
71
-      products.add(new Product("Shirt", 15.01));
72
-    ```
24
+**BONUS**: Uncomment the remove method and add the code to pass the tests.
73 25
 
74
-  2. Add this test to the `CartTest` class
75
-  ```java
76
-    @Test
77
-    public void testAddToCard(){
78
-        // Given
79
-        ArrayList<Product> products = new ArrayList();
80
-        Cart cart = new Cart(products);
26
+### Part 3 - MyHashMap
27
+If you still have no idea what a HashMap is, watch this [video](https://www.youtube.com/watch?v=shs0KM3wKv8). Notice I add the `bucketIndex` to help you determine where to store the entry. The `bucketIndex` uses the `hashCode` to try to evenly distribute the entries. 
28
+  1. `put` - find which bucket it belongs to, then add it to the list of that bucket
29
+  2. `get` - find which bucket it belongs to, then loop through the list to find the entry corresponding to the key
30
+  3. Uncomment line 178 - 196. Notice how fast it takes to run.
81 31
 
82
-        // When
83
-        Product shirt = new Product("Shirt", 1.99);
84
-        cart.addProduct(shirt);
32
+**BONUS**: Uncomment the remove method and add the code to pass the tests.
85 33
 
86
-        // Then
87
-        double expectedTotal = 1.99;
88
-        double actualTotal = cart.getProductTotal();
89
-        Assert.assertEquals(expectedTotal, actualTotal, DELTA);
90
-    }
91
-  ```
92
-    - Add a `addProduct` method to the `Cart` class
93
-    - Run the test. It should pass.
34
+## Performance
35
+Notice how long the ListMap takes to store and find 70,000 items. Notice how much faster a HashMap is. In the `MyHashMap` class, change the `BUCKET_SIZE` to `100`. Run the `MyHashMapTest` again. Notice how much faster it is. That's the power of designing and using a good data structure. It can speed up your program significantly.

+ 15
- 0
src/main/java/org/zipcoder/store/Cart.java Просмотреть файл

@@ -0,0 +1,15 @@
1
+package org.zipcoder.store;
2
+
3
+import java.util.Objects;
4
+
5
+public class Cart {
6
+    private final long id;
7
+
8
+    public Cart(long id) {
9
+        this.id = id;
10
+    }
11
+
12
+    public long getId(){
13
+        return this.id;
14
+    }
15
+}

+ 23
- 0
src/main/java/org/zipcoder/store/Entry.java Просмотреть файл

@@ -0,0 +1,23 @@
1
+package org.zipcoder.store;
2
+
3
+public class Entry {
4
+    private User key;
5
+    private Cart value;
6
+
7
+    public Entry(User key, Cart value) {
8
+        this.key = key;
9
+        this.value = value;
10
+    }
11
+
12
+    public User getKey() {
13
+        return key;
14
+    }
15
+
16
+    public Cart getValue() {
17
+        return value;
18
+    }
19
+
20
+    public void setValue(Cart value) {
21
+        this.value = value;
22
+    }
23
+}

+ 48
- 0
src/main/java/org/zipcoder/store/ListMap.java Просмотреть файл

@@ -0,0 +1,48 @@
1
+package org.zipcoder.store;
2
+
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+
6
+public class ListMap implements MyMap {
7
+    // instance field that is intialize to an ArrayList
8
+    private List<Entry> entries = new ArrayList<>();
9
+
10
+    @Override
11
+    public int size() {
12
+        return -1;
13
+    }
14
+
15
+    @Override
16
+    public boolean isEmptry() {
17
+        return false;
18
+    }
19
+
20
+    @Override
21
+    public Cart get(User key) {
22
+        // find the cart associate with the key
23
+        return null;
24
+    }
25
+
26
+    @Override
27
+    public void put(User key, Cart value) {
28
+        // add the key, value entry to the entries list
29
+    }
30
+
31
+
32
+    @Override
33
+    public List<User> getKeys() {
34
+        // get all the keys in the map
35
+        return null;
36
+    }
37
+
38
+    @Override
39
+    public List<Cart> getValues() {
40
+        // get all the values in the map
41
+        return null;
42
+    }
43
+
44
+    @Override
45
+    public Cart remove(User key) {
46
+        return null;
47
+    }
48
+}

+ 58
- 0
src/main/java/org/zipcoder/store/MyHashMap.java Просмотреть файл

@@ -0,0 +1,58 @@
1
+package org.zipcoder.store;
2
+
3
+import java.util.*;
4
+
5
+public class MyHashMap implements MyMap{
6
+    // final field that doesn't change for any object
7
+    private static final int BUCKET_SIZE = 15;
8
+
9
+    // instance field that can only be set once. It is different for every Object
10
+    private final List<Entry>[] entries;
11
+
12
+    public MyHashMap(){
13
+        entries = new List[BUCKET_SIZE];
14
+
15
+        for(int i = 0; i < BUCKET_SIZE; i++) {
16
+            entries[i] = new ArrayList<>();
17
+        }
18
+    }
19
+
20
+    @Override
21
+    public int size() {
22
+        return -1;
23
+    }
24
+
25
+    @Override
26
+    public boolean isEmptry() {
27
+        return false;
28
+    }
29
+
30
+    @Override
31
+    public Cart get(User key) {
32
+        return null;
33
+    }
34
+
35
+    @Override
36
+    public void put(User key, Cart value) {
37
+
38
+    }
39
+
40
+    @Override
41
+    public List<User> getKeys() {
42
+        return null;
43
+    }
44
+
45
+    @Override
46
+    public List<Cart> getValues() {
47
+        return null;
48
+    }
49
+
50
+    @Override
51
+    public Cart remove(User key) {
52
+        return null;
53
+    }
54
+
55
+    private int bucketIndex(User key){
56
+        return Math.abs(key.hashCode()) % entries.length;
57
+    }
58
+}

+ 47
- 0
src/main/java/org/zipcoder/store/MyMap.java Просмотреть файл

@@ -0,0 +1,47 @@
1
+package org.zipcoder.store;
2
+
3
+import java.util.List;
4
+
5
+public interface MyMap {
6
+
7
+    /**
8
+     * @return the number of entry in the map
9
+     */
10
+    public int size();
11
+
12
+    /**
13
+     * @return true if the map has one or more item in it. False otherwise.
14
+     */
15
+    public boolean isEmptry();
16
+
17
+    /**
18
+     * Return the cart associated with the user
19
+     * @param key
20
+     * @return The cart associated with the user, null if none exist.
21
+     */
22
+    public Cart get(User key);
23
+
24
+    /**
25
+     * Associate the user with the cart. If user already has a cart, then replace the old cart with this one.
26
+     * @param key The key to associate the cart
27
+     * @param value The cart to be associated
28
+     */
29
+    public void put(User key, Cart value);
30
+
31
+    /**
32
+     * @return All the users in the map
33
+     */
34
+    public List<User> getKeys();
35
+
36
+    /**
37
+     * @return All the carts in the map
38
+     */
39
+    public List<Cart> getValues();
40
+
41
+    /**
42
+     * Remove the user & cart from the map
43
+     * @param key The user to remove
44
+     * @return The cart associated with the user
45
+     */
46
+    public Cart remove(User key);
47
+}

+ 40
- 0
src/main/java/org/zipcoder/store/User.java Просмотреть файл

@@ -0,0 +1,40 @@
1
+package org.zipcoder.store;
2
+
3
+import java.util.Objects;
4
+
5
+public class User {
6
+
7
+    private long id;
8
+    private String name;
9
+
10
+    public User(){}
11
+
12
+    public User(long id) {
13
+        this.id = id;
14
+    }
15
+
16
+    public User(String name) {
17
+        this.name = name;
18
+    }
19
+
20
+    public User(long id, String name){
21
+        this.id = id;
22
+        this.name = name;
23
+    }
24
+
25
+    public long getId() {
26
+        return id;
27
+    }
28
+
29
+    public void setId(long id) {
30
+        this.id = id;
31
+    }
32
+
33
+    public String getName() {
34
+        return name;
35
+    }
36
+
37
+    public void setName(String name) {
38
+        this.name = name;
39
+    }
40
+}

+ 42
- 0
src/test/java/org/zipcoder/store/EntryTest.java Просмотреть файл

@@ -0,0 +1,42 @@
1
+package org.zipcoder.store;
2
+
3
+import org.junit.Assert;
4
+import org.junit.Test;
5
+
6
+public class EntryTest {
7
+
8
+    @Test
9
+    public void testGetKey(){
10
+        User key = new User();
11
+        Cart value = new Cart(13);
12
+        Entry entry = new Entry(key, value);
13
+
14
+        User actualKey = entry.getKey();
15
+
16
+        Assert.assertEquals(key, actualKey);
17
+    }
18
+
19
+    @Test
20
+    public void testGetValue(){
21
+        User key = new User();
22
+        Cart value = new Cart(54);
23
+        Entry entry = new Entry(key, value);
24
+
25
+        Cart actualValue = entry.getValue();
26
+
27
+        Assert.assertEquals(value, actualValue);
28
+    }
29
+
30
+
31
+    @Test
32
+    public void testGetSetValue(){
33
+        User key = new User();
34
+        Cart value = new Cart(54);
35
+        Entry entry = new Entry(key, null);
36
+
37
+        entry.setValue(value);
38
+        Cart actualValue = entry.getValue();
39
+
40
+        Assert.assertEquals(value, actualValue);
41
+    }
42
+}

+ 54
- 50
src/test/java/org/zipcoder/store/ListMapTest.java Просмотреть файл

@@ -174,54 +174,58 @@ public class ListMapTest {
174 174
         Assert.assertTrue(values.contains(cart2));
175 175
     }
176 176
 
177
-    @Test
178
-    public void testPutAndGet_WithManyItems(){
179
-        // Given
180
-        for (int i = 0; i < 70000; i++) {
181
-            myMap.put(new User(i), new Cart(i));
182
-        }
183
-
184
-
185
-        for (int i = 0; i < 70000; i++) {
186
-            // When
187
-            Cart actualCart = myMap.get(new User(i));
188
-            Cart expectedCart = new Cart(i);
189
-
190
-            // Then
191
-            Assert.assertEquals(actualCart, expectedCart);
192
-        }
193
-    }
194
-
195
-    @Test
196
-    public void testRemove(){
197
-        // Given
198
-        User user1 = new User("Lena");
199
-        Cart cart1 = new Cart(11);
200
-
201
-        User user2 = new User("Jamal");
202
-        Cart cart2 = new Cart(21);
203
-
204
-        User user3 = new User("Kelvin");
205
-        Cart cart3 = new Cart(31);
206
-
207
-        // When
208
-        myMap.put(user1, cart1);
209
-        myMap.put(user2, cart2);
210
-        myMap.put(user3, cart3);
211
-
212
-        // Then
213
-        Cart actualCart = myMap.remove(user2);
214
-
215
-        Assert.assertEquals(cart2, actualCart);
216
-        Assert.assertNull(myMap.get(user2));
217
-    }
218
-
219
-    @Test
220
-    public void testRemove_CartNotInTheMap(){
221
-        // Given
222
-        User user1 = new User("Lena");
223
-
224
-        // When & Then
225
-        Assert.assertNull(myMap.remove(user1));
226
-    }
177
+//    I commented this out because it takes a long time to run. Uncomment it when implement your put method, uncomment this test
178
+//    @Test
179
+//    public void testPutAndGet_WithManyItems(){
180
+//        // Given
181
+//        int numberOfEntries = 70000;
182
+//
183
+//        for (int i = 0; i < numberOfEntries; i++) {
184
+//            myMap.put(new User(i), new Cart(i));
185
+//        }
186
+//
187
+//
188
+//        for (int i = 0; i < numberOfEntries; i++) {
189
+//            // When
190
+//            Cart actualCart = myMap.get(new User(i));
191
+//            Cart expectedCart = new Cart(i);
192
+//
193
+//            // Then
194
+//            Assert.assertEquals(actualCart, expectedCart);
195
+//        }
196
+//    }
197
+
198
+//    BONUS
199
+//    @Test
200
+//    public void testRemove(){
201
+//        // Given
202
+//        User user1 = new User("Lena");
203
+//        Cart cart1 = new Cart(11);
204
+//
205
+//        User user2 = new User("Jamal");
206
+//        Cart cart2 = new Cart(21);
207
+//
208
+//        User user3 = new User("Kelvin");
209
+//        Cart cart3 = new Cart(31);
210
+//
211
+//        // When
212
+//        myMap.put(user1, cart1);
213
+//        myMap.put(user2, cart2);
214
+//        myMap.put(user3, cart3);
215
+//
216
+//        // Then
217
+//        Cart actualCart = myMap.remove(user2);
218
+//
219
+//        Assert.assertEquals(cart2, actualCart);
220
+//        Assert.assertNull(myMap.get(user2));
221
+//    }
222
+//
223
+//    @Test
224
+//    public void testRemove_CartNotInTheMap(){
225
+//        // Given
226
+//        User user1 = new User("Lena");
227
+//
228
+//        // When & Then
229
+//        Assert.assertNull(myMap.remove(user1));
230
+//    }
227 231
 }

+ 53
- 50
src/test/java/org/zipcoder/store/MyHashMapTest.java Просмотреть файл

@@ -174,54 +174,57 @@ public class MyHashMapTest {
174 174
         Assert.assertTrue(values.contains(cart2));
175 175
     }
176 176
 
177
-    @Test
178
-    public void testPutAndGet_WithManyItems(){
179
-        // Given
180
-        for (int i = 0; i < 70000; i++) {
181
-            myMap.put(new User(i), new Cart(i));
182
-        }
183
-
184
-
185
-        for (int i = 0; i < 70000; i++) {
186
-            // When
187
-            Cart actualCart = myMap.get(new User(i));
188
-            Cart expectedCart = new Cart(i);
189
-
190
-            // Then
191
-            Assert.assertEquals(actualCart, expectedCart);
192
-        }
193
-    }
194
-
195
-    @Test
196
-    public void testRemove(){
197
-        // Given
198
-        User user1 = new User("Lena");
199
-        Cart cart1 = new Cart(11);
200
-
201
-        User user2 = new User("Jamal");
202
-        Cart cart2 = new Cart(21);
203
-
204
-        User user3 = new User("Kelvin");
205
-        Cart cart3 = new Cart(31);
206
-
207
-        // When
208
-        myMap.put(user1, cart1);
209
-        myMap.put(user2, cart2);
210
-        myMap.put(user3, cart3);
211
-
212
-        // Then
213
-        Cart actualCart = myMap.remove(user2);
214
-
215
-        Assert.assertEquals(cart2, actualCart);
216
-        Assert.assertNull(myMap.get(user2));
217
-    }
218
-
219
-    @Test
220
-    public void testRemove_CartNotInTheMap(){
221
-        // Given
222
-        User user1 = new User("Lena");
223
-
224
-        // When & Then
225
-        Assert.assertNull(myMap.remove(user1));
226
-    }
177
+//    I commented this out because it takes a long time to run. Uncomment it when implement your put method, uncomment this test
178
+//    @Test
179
+//    public void testPutAndGet_WithManyItems(){
180
+//        // Given
181
+//        int numberOfEntries = 70000;
182
+//
183
+//        for (int i = 0; i < numberOfEntries; i++) {
184
+//            myMap.put(new User(i), new Cart(i));
185
+//        }
186
+//
187
+//
188
+//        for (int i = 0; i < numberOfEntries; i++) {
189
+//            // When
190
+//            Cart actualCart = myMap.get(new User(i));
191
+//            Cart expectedCart = new Cart(i);
192
+//
193
+//            // Then
194
+//            Assert.assertEquals(actualCart, expectedCart);
195
+//        }
196
+//    }
197
+
198
+//    @Test
199
+//    public void testRemove(){
200
+//        // Given
201
+//        User user1 = new User("Lena");
202
+//        Cart cart1 = new Cart(11);
203
+//
204
+//        User user2 = new User("Jamal");
205
+//        Cart cart2 = new Cart(21);
206
+//
207
+//        User user3 = new User("Kelvin");
208
+//        Cart cart3 = new Cart(31);
209
+//
210
+//        // When
211
+//        myMap.put(user1, cart1);
212
+//        myMap.put(user2, cart2);
213
+//        myMap.put(user3, cart3);
214
+//
215
+//        // Then
216
+//        Cart actualCart = myMap.remove(user2);
217
+//
218
+//        Assert.assertEquals(cart2, actualCart);
219
+//        Assert.assertNull(myMap.get(user2));
220
+//    }
221
+//
222
+//    @Test
223
+//    public void testRemove_CartNotInTheMap(){
224
+//        // Given
225
+//        User user1 = new User("Lena");
226
+//
227
+//        // When & Then
228
+//        Assert.assertNull(myMap.remove(user1));
229
+//    }
227 230
 }