Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions 3-0-java-core/src/main/java/com/bobocode/file_stats/FileStats.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.bobocode.file_stats;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

/**
* {@link FileStats} provides an API that allow to get character statistic based on text file. All whitespace characters
* are ignored.
*/
public class FileStats {
private final Map<Character, Long> characterCountMap;
private final char mostPopularCharacter;

/**
* Creates a new immutable {@link FileStats} objects using data from text file received as a parameter.
*
* @param fileName input text file name
* @return new FileStats object created from text file
*/
public static FileStats from(String fileName) {
return new FileStats(fileName);
}

private FileStats(String fileName) {
Path filePath = getFilePath(fileName);
characterCountMap = computeCharacterMap(filePath);
mostPopularCharacter = findMostPopularCharacter(characterCountMap);
}

private Path getFilePath(String fileName) {
Objects.requireNonNull(fileName);
URL fileUrl = getFileUrl(fileName);
try {
return Paths.get(fileUrl.toURI());
} catch (URISyntaxException e) {
throw new FileStatsException("Wrong file path", e);
}
}

private URL getFileUrl(String fileName) {
URL fileUrl = getClass().getClassLoader().getResource(fileName);
if (fileUrl == null) {
throw new FileStatsException("Wrong file path");
}
return fileUrl;
}

private Map<Character, Long> computeCharacterMap(Path filePath) {
try (Stream<String> lines = Files.lines(filePath)) {
return collectCharactersToCountMap(lines);
} catch (IOException e) {
throw new FileStatsException("Cannot read the file", e);
}
}

private Map<Character, Long> collectCharactersToCountMap(Stream<String> linesStream) {
return linesStream
.flatMapToInt(String::chars)
.filter(a -> a != 32) // filter whitespace
.mapToObj(c -> (char) c)
.collect(groupingBy(identity(), counting()));
}

/**
* Returns a number of occurrences of the particular character.
*
* @param character a specific character
* @return a number that shows how many times this character appeared in a text file
*/
public int getCharCount(char character) {
return characterCountMap.get(character).intValue();
}

/**
* Returns a character that appeared most often in the text.
*
* @return the most frequently appeared character
*/
public char getMostPopularCharacter() {
return mostPopularCharacter;
}

private char findMostPopularCharacter(Map<Character, Long> characterCountMap) {
return characterCountMap.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getValue))
.get()
.getKey();
}

/**
* Returns {@code true} if this character has appeared in the text, and {@code false} otherwise
*
* @param character a specific character to check
* @return {@code true} if this character has appeared in the text, and {@code false} otherwise
*/
public boolean containsCharacter(char character) {
return characterCountMap.containsKey(character);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bobocode.file_stats;

public class FileStatsException extends RuntimeException{
public FileStatsException(String message) {
super(message);
}

public FileStatsException(String message, Throwable cause) {
super(message, cause);
}
}
21 changes: 21 additions & 0 deletions 3-0-java-core/src/main/java/com/bobocode/file_stats/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# <img src="https://raw.githubusercontent.com/bobocode-projects/resources/master/image/logo_transparent_background.png" height=50/>Files Stats exercise :muscle:
Improve your Java SE skills
### Task
`FileStats` is an API that allows you to get character statistics based on text file. Your job is to
implement the *todo* section of that class. Please note, that each object should be immutable and should not allow to
reload or refresh input data.

To verify your implementation, run `FileStatsTest.java`

### Pre-conditions :heavy_exclamation_mark:
You're supposed to know how to work with text files and be able to write Java code

### How to start :question:
* Just clone the repository and create a branch **exercise/your_username** if you want your code to be reviewed
* Start implementing the **todo** section and verify your changes by running tests
* If you don't have enough knowledge about this domain, check out the [links below](#related-materials-information_source)
* Don't worry if you got stuck, checkout the **exercise/completed** branch and see the final implementation

### Related materials :information_source:
* [Stream API tutorial](https://github.com/bobocode-projects/java-functional-features-tutorial/tree/master/stream-api)

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.bobocode.file_stats;

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import static org.assertj.core.api.Assertions.*;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class FileStatsTest {

@Test
@Order(1)
void createFileStatsFromExistingFile() {
FileStats fileStats = FileStats.from("sotl.txt");
}

@Test
@Order(2)
void createFileStatsFromNonExistingFile() {
assertThatThrownBy(() -> FileStats.from("blahblah.txt")).isInstanceOf(FileStatsException.class);
}

@Test
@Order(3)
void getCharCount() {
FileStats lambdaArticleFileStats = FileStats.from("sotl.txt");
FileStats springCloudArticleFileStats = FileStats.from("scosb.txt");

int aCharCountInLambdaArticle = lambdaArticleFileStats.getCharCount('a');
int bCharCountInSpringArticle = springCloudArticleFileStats.getCharCount('b');

assertThat(aCharCountInLambdaArticle).isEqualTo(2345);
assertThat(bCharCountInSpringArticle).isEqualTo(4);
}

@Test
@Order(4)
void getMostPopularCharacter() {
FileStats lambdaArticleFileStats = FileStats.from("sotl.txt");
FileStats springCloudArticleFileStats = FileStats.from("scosb.txt");

char mostPopularCharacterInLambdaArticle = lambdaArticleFileStats.getMostPopularCharacter();
char mostPopularCharacterInSpringArticle = springCloudArticleFileStats.getMostPopularCharacter();

System.out.println(mostPopularCharacterInSpringArticle);

assertThat(mostPopularCharacterInLambdaArticle).isEqualTo('e');
assertThat(mostPopularCharacterInSpringArticle).isEqualTo('e');
}

@Test
@Order(5)
void containsCharacter() {
FileStats lambdaArticleFileStats = FileStats.from("sotl.txt");
FileStats springCloudArticleFileStats = FileStats.from("scosb.txt");

boolean lambdaArticleContainsExistingCharacter = lambdaArticleFileStats.containsCharacter('a');
boolean lambdaArticleContainsWhitespace = lambdaArticleFileStats.containsCharacter(' ');
boolean springArticleContainsExistingCharacter = springCloudArticleFileStats.containsCharacter('b');
boolean springArticleContainsWhitespace = springCloudArticleFileStats.containsCharacter(' ');

assertThat(lambdaArticleContainsExistingCharacter).isTrue();
assertThat(lambdaArticleContainsWhitespace).isFalse();
assertThat(springArticleContainsExistingCharacter).isTrue();
assertThat(springArticleContainsWhitespace).isFalse();
}
}
3 changes: 3 additions & 0 deletions 3-0-java-core/src/test/resources/scosb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
We’re pleased to announce that the 2.0.1 release of Spring Cloud Open Service Broker is now available. This release resolves a few issues that were raised since the 2.0.0 release. Thank you to the community for your interest and feedback!

Spring Cloud Open Service Broker is a framework for building Spring Boot applications that implement the Open Service Broker API. The Open Service Broker API project allows developers to deliver services to applications running within cloud native platforms such as Cloud Foundry, Kubernetes, and OpenShift.
Loading