refactor(hw-01): rename source directory to solution

This commit is contained in:
user
2026-09-20 12:41:44 +04:00
parent 9f329b50d7
commit 5f59609657
12 changed files with 0 additions and 0 deletions
@@ -0,0 +1,43 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/9.7.1/userguide/building_java_projects.html in the Gradle documentation.
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
application
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Use JUnit Jupiter for testing.
testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// This dependency is used by the application.
implementation(libs.guava)
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
// Define the main class for the application.
mainClass = "org.example.App"
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
@@ -0,0 +1,14 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example;
public class App {
public String getGreeting() {
return "Hello World!";
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}
@@ -0,0 +1,130 @@
package org.example;
import java.util.Objects;
public class MyHashMap<Key, Value> {
private Key[] keys;
private Value[] values;
private boolean[] occupied;
private boolean[] deleted;
private int size;
public MyHashMap(int capacity) {
keys = createArray(capacity);
values = createArray(capacity);
occupied = new boolean[capacity];
deleted = new boolean[capacity];
}
public Value get(Key key) {
int index = findIndex(key);
return index == -1 ? null : values[index];
}
public Value put(Key key, Value value) {
if (size == keys.length) {
resize();
}
int index = findIndex(key);
if (index != -1) {
Value oldValue = values[index];
values[index] = value;
return oldValue;
}
index = findEmptyIndex(key);
keys[index] = key;
values[index] = value;
occupied[index] = true;
deleted[index] = false;
size++;
return null;
}
public Value remove(Key key) {
int index = findIndex(key);
if (index == -1) {
return null;
}
Value oldValue = values[index];
occupied[index] = false;
deleted[index] = true;
size--;
return oldValue;
}
private int findIndex(Key key) {
int index = index(key);
int start = index;
while (occupied[index] || deleted[index]) {
if (occupied[index] && Objects.equals(keys[index], key)) {
return index;
}
index = (index + 1) % keys.length;
if (index == start) {
return -1;
}
}
return -1;
}
private int findEmptyIndex(Key key) {
int index = index(key);
int start = index;
int deletedIndex = -1;
while (occupied[index]) {
if (Objects.equals(keys[index], key)) {
return index;
}
index = (index + 1) % keys.length;
if (index == start) {
return deletedIndex;
}
}
return deletedIndex == -1 ? index : deletedIndex;
}
private int index(Key key) {
return Math.floorMod(key == null ? 0 : key.hashCode(), keys.length);
}
private void resize() {
Key[] oldKeys = keys;
Value[] oldValues = values;
boolean[] oldOccupied = occupied;
keys = createArray(oldKeys.length * 2);
values = createArray(oldValues.length * 2);
occupied = new boolean[keys.length];
deleted = new boolean[keys.length];
size = 0;
for (int i = 0; i < oldKeys.length; i++) {
if (oldOccupied[i]) {
put(oldKeys[i], oldValues[i]);
}
}
}
@SuppressWarnings("unchecked")
private <T> T[] createArray(int capacity) {
return (T[]) new Object[capacity];
}
}
@@ -0,0 +1,14 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AppTest {
@Test void appHasAGreeting() {
App classUnderTest = new App();
assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
}
}
@@ -0,0 +1,319 @@
package org.example;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class MyHashMapTest {
@Test
void shouldPutAndGet() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put("A", 10);
assertEquals(10, map.get("A"));
}
@Test
void shouldUpdateValue() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put("A", 10);
map.put("A", 20);
assertEquals(20, map.get("A"));
}
@Test
void shouldReturnOldValueWhenUpdating() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
assertNull(map.put("A", 10));
assertEquals(10, map.put("A", 20));
}
@Test
void shouldReturnNullForMissingKey() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
assertNull(map.get("A"));
}
@Test
void shouldRemoveValue() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put("A", 10);
assertEquals(10, map.remove("A"));
assertNull(map.get("A"));
}
@Test
void shouldReturnNullWhenRemovingMissingKey() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
assertNull(map.remove("A"));
}
@Test
void shouldHandleCollision() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
assertEquals("A", map.get(1));
assertEquals("B", map.get(5));
}
@Test
void shouldHandleRemoveWithCollision() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.put(9, "C");
assertEquals("A", map.remove(1));
assertEquals("B", map.get(5));
assertEquals("C", map.get(9));
}
@Test
void shouldResize() {
MyHashMap<Integer, String> map = new MyHashMap<>(2);
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
assertEquals("A", map.get(1));
assertEquals("B", map.get(2));
assertEquals("C", map.get(3));
}
@Test
void shouldReuseDeletedSlot() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.remove(1);
map.put(9, "C");
assertEquals("C", map.get(9));
assertEquals("B", map.get(5));
}
@Test
void shouldHandleNullKey() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put(null, 100);
assertEquals(100, map.get(null));
assertEquals(100, map.remove(null));
assertNull(map.get(null));
}
@Test
void shouldHandleNullValue() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
assertNull(map.put("A", null));
assertNull(map.get("A"));
assertNull(map.put("A", 10));
assertEquals(10, map.get("A"));
}
@Test
void shouldUpdateNullValue() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put("A", 10);
assertEquals(10, map.put("A", null));
assertNull(map.get("A"));
}
@Test
void shouldRemoveMiddleElementFromCollisionChain() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.put(9, "C");
assertEquals("B", map.remove(5));
assertEquals("A", map.get(1));
assertNull(map.get(5));
assertEquals("C", map.get(9));
}
@Test
void shouldRemoveLastElementFromCollisionChain() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.put(9, "C");
assertEquals("C", map.remove(9));
assertEquals("A", map.get(1));
assertEquals("B", map.get(5));
assertNull(map.get(9));
}
@Test
void shouldReinsertRemovedKey() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put("A", 10);
assertEquals(10, map.remove("A"));
assertNull(map.get("A"));
assertNull(map.put("A", 20));
assertEquals(20, map.get("A"));
}
@Test
void shouldKeepCollidingEntriesAfterRemovingFirst() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.put(9, "C");
map.remove(1);
assertEquals("B", map.get(5));
assertEquals("C", map.get(9));
}
@Test
void shouldKeepCollidingEntriesAfterRemovingMiddle() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.put(9, "C");
map.put(13, "D");
map.remove(5);
assertEquals("A", map.get(1));
assertEquals("C", map.get(9));
assertEquals("D", map.get(13));
}
@Test
void shouldHandleManyCollisions() {
MyHashMap<Integer, String> map = new MyHashMap<>(2);
map.put(1, "A");
map.put(3, "B");
map.put(5, "C");
map.put(7, "D");
map.put(9, "E");
assertEquals("A", map.get(1));
assertEquals("B", map.get(3));
assertEquals("C", map.get(5));
assertEquals("D", map.get(7));
assertEquals("E", map.get(9));
}
@Test
void shouldResizeAndKeepCollisions() {
MyHashMap<Integer, String> map = new MyHashMap<>(2);
map.put(1, "A");
map.put(3, "B");
map.put(5, "C");
map.put(7, "D");
map.put(9, "E");
map.put(11, "F");
assertEquals("A", map.get(1));
assertEquals("B", map.get(3));
assertEquals("C", map.get(5));
assertEquals("D", map.get(7));
assertEquals("E", map.get(9));
assertEquals("F", map.get(11));
}
@Test
void shouldUpdateCollidingKey() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(5, "B");
map.put(9, "C");
assertEquals("B", map.put(5, "NEW"));
assertEquals("A", map.get(1));
assertEquals("NEW", map.get(5));
assertEquals("C", map.get(9));
}
@Test
void shouldHandleEqualButDifferentStringInstances() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
map.put(new String("A"), 10);
assertEquals(10, map.get(new String("A")));
assertEquals(10, map.remove(new String("A")));
}
@Test
void shouldNotAffectOtherKeysWhenUpdating() {
MyHashMap<Integer, String> map = new MyHashMap<>(4);
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
map.put(2, "UPDATED");
assertEquals("A", map.get(1));
assertEquals("UPDATED", map.get(2));
assertEquals("C", map.get(3));
}
@Test
void shouldNotFindKeyAfterRemoveAndResize() {
MyHashMap<Integer, String> map = new MyHashMap<>(2);
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
map.put(4, "D");
map.remove(2);
assertNull(map.get(2));
assertEquals("A", map.get(1));
assertEquals("C", map.get(3));
assertEquals("D", map.get(4));
}
@Test
void shouldHandleRepeatedPutAndRemove() {
MyHashMap<String, Integer> map = new MyHashMap<>(4);
for (int i = 0; i < 100; i++) {
assertNull(map.put("A", i));
assertEquals(i, map.get("A"));
assertEquals(i, map.remove("A"));
assertNull(map.get("A"));
}
}
}