Проект Maven — коллекции HashMap и HashSet с тестированием JUnit
Во многих программах мы будем работать с HashMap и HashSet, и всегда существует путаница, когда использовать HashMap и когда использовать HashSet. В качестве примера проекта взят вариант использования, содержащий класс «GeekAuthor», и он имеет разные атрибуты, а именно
- имя автора
- идентификатор автора
- круг интересов
- опубликованные статьи
Давайте попробуем добавить данные «GeekAuthor» как в HashMap, так и в HashSet по отдельности и проверим поведение по одному. Наряду с JUNIT мы также можем эффективно тестировать.
Пример проекта Maven
Структура проекта:
Проект подготовлен как тип maven и, следовательно, все зависимости, необходимые для проекта, присутствуют в
пом.xml
XML
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 < modelVersion >4.0.0</ modelVersion > < groupId >com.gfg.CollectionServicesInJava</ groupId > < artifactId >CollectionServicesInJava</ artifactId > < packaging >jar</ packaging > < version >1.0-SNAPSHOT</ version > < properties > < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding > < maven.compiler.source >1.8</ maven.compiler.source > < maven.compiler.target >1.8</ maven.compiler.target > < junit.version >5.3.1</ junit.version > < pitest.version >1.4.3</ pitest.version > </ properties > < dependencies > <!-- junit 5, unit test --> < dependency > < groupId >org.junit.jupiter</ groupId > < artifactId >junit-jupiter-engine</ artifactId > < version >${junit.version}</ version > < scope >test</ scope > </ dependency > </ dependencies > < build > < finalName >maven-mutation-testing</ finalName > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-surefire-plugin</ artifactId > < version >3.0.0-M1</ version > </ plugin > < plugin > < groupId >org.pitest</ groupId > < artifactId >pitest-maven</ artifactId > < version >${pitest.version}</ version > < executions > < execution > < id >pit-report</ id > < phase >test</ phase > < goals > < goal >mutationCoverage</ goal > </ goals > </ execution > </ executions > <!-- Need this to support JUnit 5 --> < dependencies > < dependency > < groupId >org.pitest</ groupId > < artifactId >pitest-junit5-plugin</ artifactId > < version >0.8</ version > </ dependency > </ dependencies > < configuration > < targetClasses > < param >com.gfg.CollectionServicesInJava.*CollectionServicesInJava*</ param > </ targetClasses > < targetTests > < param >com.gfg.CollectionServicesInJava.*</ param > </ targetTests > </ configuration > </ plugin > </ plugins > </ build > </ project > |
Поскольку мы собираемся добавить GeekAuthors, нам нужен класс модели для него.
GeekAuthor.java
Java
package com.gfg.CollectionServicesInJava; public class GeekAuthor { public GeekAuthor(String authorName, int authorId, String areaOfInterest, int publishedArticles) { super (); this .authorName = authorName; this .authorId = authorId; this .areaOfInterest = areaOfInterest; this .publishedArticles = publishedArticles; } public GeekAuthor() { // via setter methods, rest fields are done } String authorName; int authorId; String areaOfInterest; int publishedArticles; public String getAuthorName() { return authorName; } public void setAuthorName(String authorName) { this .authorName = authorName; } public int getAuthorId() { return authorId; } public void setAuthorId( int authorId) { this .authorId = authorId; } public String getAreaOfInterest() { return areaOfInterest; } public void setAreaOfInterest(String areaOfInterest) { this .areaOfInterest = areaOfInterest; } public int getPublishedArticles() { return publishedArticles; } public void setPublishedArticles( int publishedArticles) { this .publishedArticles = publishedArticles; } // We need to override 2 methods namely // equals and hashcode whenever we no need // to store two author objects // if their names are same @Override public boolean equals(Object o) { if (o instanceof GeekAuthor) { GeekAuthor other = (GeekAuthor) o; return authorName.equals(other.getAuthorName()); } return false ; } @Override public int hashCode() { return authorName.hashCode(); } } |
Здесь нам нужно обратить внимание на два конкретных метода, а именно «equals» и «hashCode». Они должны быть переопределены в соответствии с нашими требованиями. Эти два метода по существу необходимы для проверки того, являются ли объекты дубликатами или нет. Они снова приведены здесь для справки.
// We need to override 2 methods namely equals // and hashcode whenever we no need // to store two author objects // if their names are same @Override public boolean equals(Object o) { if (o instanceof GeekAuthor) { GeekAuthor other = (GeekAuthor) o; return authorName.equals(other.getAuthorName()); } return false; } @Override public int hashCode() { return authorName.hashCode(); }
Этот набор кода очень важен, и только функциональность HashSet запрещает дублирование. Здесь нам нужно знать, что HashMap допускает дублирование ключей, но что произойдет, так это то, что новые добавленные данные будут перезаписаны вместо старых данных. Например
authorMap.put("Rachel",new GeekAuthor("Rachel", 1, "Java", 200)); authorMap.put("Monica",new GeekAuthor("Monica", 1, "Python", 100)); authorMap.put("Rachel",new GeekAuthor("Phoebe", 1, "Java", 100)); In line 1 and 3, "Rachel" is the key. Hence finally in the HashMap we can able to see only 2 entries only and when we try to retrieve the data for "Rachel" key, we will get authorName as Phoebe, authorId as 1 etc., i.e. 1st data is overwritten
Теперь, что касается HashSet, если мы попытаемся добавить повторяющиеся данные, они вообще не будут учитываться из-за существующих двух методов, а именно «equals» и «hashCode».
GeekAuthor rachel = new GeekAuthor("Rachel", 1, "Java", 200); GeekAuthor monica = new GeekAuthor("Monica", 1, "Python", 100); GeekAuthor phoebe = new GeekAuthor("Rachel", 1, "Java", 200); authorSet.add(rachel); authorSet.add(monica); authorSet.add(phoebe); Here though "phoebe" named author object is created and since it is a duplicate value ("rachel" named author objectis already added with the same data, finally only 2 author data is there.
Давайте посмотрим полный набор кодов через
HashMapCollectionServicesInJava.java
Java
import java.util.HashMap; public class HashMapCollectionServicesInJava { // In order to represent HashMap does not allow // duplicates in a HashMap for the same key "Rachel", // two separate author data is added // Though adding is allowed, instead of keeping // 3 different entries, only 2 will be the size and for // "Rachel" key, last data is updated public int addAuthors(HashMap authorMap) { authorMap.put( "Rachel" , new GeekAuthor( "Rachel" , 1 , "Java" , 200 )); authorMap.put( "Monica" , new GeekAuthor( "Monica" , 1 , "Python" , 100 )); authorMap.put( "Rachel" , new GeekAuthor( "Phoebe" , 1 , "Java" , 100 )); return authorMap.size(); } public int getAuthors(HashMap authors) { return authors.size(); } public String getAuthorName(HashMap authorMap,String authorNameKey) { GeekAuthor geekAuthor = new GeekAuthor(); if (authorMap.containsKey(authorNameKey)) { // Mapping the retrieved value geekAuthor = (GeekAuthor) authorMap.get(authorNameKey); } return geekAuthor.getAuthorName(); } } |
HashSetCollectionServicesInJava.java
Java
import java.util.HashSet; import java.util.Set; public class HashSetCollectionServicesInJava { public int addAuthorsViaHashSet(Set authorSet) { GeekAuthor rachel = new GeekAuthor( "Rachel" , 1 , "Java" , 200 ); GeekAuthor monica = new GeekAuthor( "Monica" , 1 , "Python" , 100 ); GeekAuthor phoebe = new GeekAuthor( "Rachel" , 1 , "Java" , 200 ); authorSet.add(rachel); authorSet.add(monica); authorSet.add(phoebe); return authorSet.size(); } public int getAuthors(HashSet authorsSet) { return authorsSet.size(); } public String getAuthorName(HashSet author,GeekAuthor geekAuthor) { if (author.contains(geekAuthor)) { // Mapping the retrieved value return geekAuthor.getAuthorName(); } return null ; } } |
Хорошо, теперь давайте проверим это. Нам нужно проверить, верны ли наши предположения. т.е. то, что происходит во время добавления хэш-карты, и то, что происходит при добавлении хэш-набора, мы можем обосновать приведенными ниже тестами.
TestCollectionServicesJava.java
Java
import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.HashMap; import java.util.HashSet; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class TestCollectionServicesJava { @DisplayName ( "Test check for adding geekauthors in HashMap collection " ) @Test public void testCheckForAdditionOfAuthorsInHashMap() { HashMap<String,GeekAuthor> authors = new HashMap<String,GeekAuthor>(); HashMapCollectionServicesInJava hashMapCollectionServicesJavaObject = new HashMapCollectionServicesInJava(); assertEquals( true , hashMapCollectionServicesJavaObject.getAuthors(authors) == 0 ); // adding few authors hashMapCollectionServicesJavaObject.addAuthors(authors); // "Rachel" key is duplicated and hence we expect only 2 assertEquals( true , hashMapCollectionServicesJavaObject.getAuthors(authors) == 2 ); // "Rachel" key is duplicated, now lets assert that the // last taken value is updated for "Rachel" key assertEquals( true , hashMapCollectionServicesJavaObject.getAuthorName(authors, "Rachel" ).equalsIgnoreCase( "Phoebe" )); } @DisplayName ( "Test check for adding geekauthors in HashSet collection " ) @Test РЕКОМЕНДУЕМЫЕ СТАТЬИ |