drcarter의 DevLog

Guava: Google Core Libraries for Java

  • Base

 - Objects.equal() : equal 비교시 null 체크를 하지 않아도 된다.

 - Objects.hashCode() : hash코드 생성을 보다 쉽게 만들 수 있다.

 - Objects.toStringHelper() : toString객체를 보다 쉽게 만들 수 잇다.

  -> 일반적인 코드 :

public class Book {
private String title;
private String writer;
private int price;

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getWriter() {
return writer;
}

public void setWriter(String writer) {
this.writer = writer;
}

public int getPrice() {
return price;
}

public void setPrice(int price) {
this.price = price;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Book book = (Book) o;

if (price != book.price) return false;
if (title != null ? !title.equals(book.title) : book.title != null) return false;
return !(writer != null ? !writer.equals(book.writer) : book.writer != null);

}

@Override
public int hashCode() {
int result = title != null ? title.hashCode() : 0;
result = 31 * result + (writer != null ? writer.hashCode() : 0);
result = 31 * result + price;
return result;
}

@Override
public String toString() {
return "Book{" +
"title='" + title + '\'' +
", writer='" + writer + '\'' +
", price=" + price +
'}';
}
}

  -> Guava를 이용한 코드

public class Book {
private String title;
private String writer;
private int price;

public Book(String title, String writer, int price) {
this.title = title;
this.writer = writer;
this.price = price;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
Preconditions.checkNotNull(title);
this.title = title;
}

public String getWriter() {
return writer;
}

public void setWriter(String writer) {
this.writer = writer;
}

public int getPrice() {
return price;
}

public void setPrice(int price) {
this.price = price;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equal(this.title, book.title) && Objects.equal(this.writer, book.writer)
&& this.price == book.price;

}

@Override
public int hashCode() {
return Objects.hashCode(this.title, this.writer, this.price);
}

@Override
public String toString() {
return Objects.toStringHelper(this)
.add("title", title)
.add("writer", writer)
.add("price", price)
.toString();
}
}

작성하다보니 Objects.toStringHelper 가 deprecated가 되었네요.. 이건 MoreObject.toStringHelper()를 이용하면 됩니다.

 - Preconditions : 객체 정보의 null과 같은 정보가 있는지를 미리 확인하여 exception을 낸다.

  -> 일반적인 코드

public void setTitle(String title) {

if(title == null) {
throw new NullPointerException("title must not be null!");
}

this.title = title;
}

  -> Preconditions를 이용

public void setTitle(String title) {
Preconditions.checkNotNull(title);
this.title = title;
}

 - Joiner : Collections객체들이나 array객체들의 정보들을 string으로 변경해준다.

List names = new ArrayList<>();
names.add("test1");
names.add("test2");
names.add("test3");

Joiner.on(", ").join(names); // test1, test2, test3

 - Splitter : Joiner와 반대로 split 캐릭터를 기준으로 Iterator객체로 변환하여 준다.

Iterator names = Splitter.on(",")
.trimResults()
.omitEmptyStrings()
.split("test1, test2, test3").iterator();

names.next(); //test1
names.next(); //test2
names.next(); //test3

  • Collections
 - Collections객체를 생각하면 기본적으로 List, Set, Map등을 생각합니다. 그리고 이런 Collection 객체들을 생성할 때 new 를 통해 객체 생성을 하죠.
기본적으로 List 를 본다면 new ArrayList<Strig>();와 같이 합니다. 하지만 Guava에서는 static factory 생성자를 이용합니다.

Lists.newArrayList();
Sets.newHashSet();
Maps.newHashMap();

 - Immutable Collections : 변경 불가능한 Collection.. 객체들에 대한 의도하지 않은 변경을 막고 Thread-Safe 한 객체를 만들 수 있다.

Set<String> nameSet = Collections.unmodifiableSet(new LinkedHashSet<String>(Arrays.asList("test1", "test2", "test3")));
Set<String> nameSet = ImmutableSet.of("test1", "test2", "test3");

이와 같이 변경불가능 객체를 만들 때 기존 코드보다 간결하게 만들 수 있다. Set 이와에 Map에 대해서도 알아보면.

Map<String, Integer> mapValue1 = new LinkedHashMap<>();
mapValue1.put("test1", 1);
mapValue1.put("test2", 2);
mapValue1.put("test3", 3);
Map<String, Integer> unModifiedMap = Collections.unmodifiableMap(mapValue1);

Map<String, Integer> mapValue2 = ImmutableMap.<String, Integer>builder()
.put("test1", 1).put("test2", 2).put("test3", 3)
.build();

Map<String, Integer> mapValue3 = ImmutableMap.of("test1", 1, "test2", 2, "test3", 3);

이와 Immutable Collection이 있는 것들은
  • ImmutableCollection
  • ImmutableList
  • ImmutableSet
  • ImmutableSortedSet
  • ImmutableMap
  • ImmutableSortedMap
  • ImmutableMultiset
  • ImmutableSortedMultiset
  • ImmutableMultimap
  • ImmutableListMultimap
  • ImmutableSetMultimap
  • ImmutableBiMap
  • ImmutableClassToInstanceMap
  • ImmutableTable
이렇게 존재한다. 기존 java 코드보다는 훨씬 간결한 코드를 이용할 수 있다.
 - BiMap : key에 대한 unique한 값을 보장하는게 아니라 value에 대한 unique 성을 보장한다.
 - MultiSet : element의 중복을 허용한다.
 - MultiMap : Map이 Key의 중복을 허용하지 않지만,  MultiMap은 Key의 중복을 허용한다. MultiMap은 Map<K, Collection<V>>의 특성을 가지고 있다.

  • Functional programming

public interface Function {
@Nullable T apply(@Nullable F input);
}

이와 같이 F를 입력 받아서 T의 결과를 리턴한다.
예를 든다면 마일을 입력받아서 킬로미터로 출력한다.

Function<Integer, Double> calcMileToKillometer = new Function<Integer, Double>() {
@Override
public Double apply(@Nullable Integer input) {
return input * 1.60934;
}
};

double miles = calcMileToKillometer.apply(1);

- filter / transform
 객체에 있는 특정 값들이 속한 객체들만 골라낸 Collection을 만들거나, 특정 값들만 뽑아낸 새로운 Collection을 만들어 낼 수 있다.

List<Book> bookList = ImmutableList.of(new Book("Android", "test", 100), new Book("Java", "test2", 200), new Book("Object", "test3", 300));
List<Book> androidBookList = ImmutableList.copyOf(Collections2.filter(bookList, new Predicate<Book>() {
@Override
public boolean apply(@Nullable Book input) {
return "Android".equals(input.getTitle());
}
}));

List<String> titleList = ImmutableList.copyOf(Collections2.transform(bookList, new Function<Book, String>() {
@Override
public String apply(@Nullable Book input) {
return input.getTitle();
}
}));


우선 제가 자주 사용하는 것들로만 정리..
내부적으로 아직 @Beta annotation이 된 것들도 많아서.. 아직 그것들에 대해서는 적어두진 않았습니다.