118
Очень вкусный фрукт Guava

Очень вкусный фрукт Guava

Embed Size (px)

Citation preview

Page 1: Очень вкусный фрукт Guava

Очень вкусный фруктGuava

Page 2: Очень вкусный фрукт Guava

Вместо эпиграфаНе изобретайте колесо. Если вам нужно сделать нечто, что кажется

вполне обычным, в библиотеках уже может быть класс, который делает это. Вообще говоря, программный код в библиотеке наверняка окажется лучше кода, который вы напишете сами, а со временем он может стать еще лучше. Мы не ставим под сомнение ваши способности как программиста, однако библиотечному коду уделяется гораздо больше внимания, чем может позволить себе средний разработчик при реализации тех же функций.

Джошуа Блох. Эффективное программирование на Java.

Статья 47 “Изучите библиотеки и пользуйтесь ими”2

Page 3: Очень вкусный фрукт Guava

Философия библиотеки

● Тщательно разработана● Протестирована● Оптимизирована● Только повсеместно используемые

функции попадают в библиотеку

3

Page 4: Очень вкусный фрукт Guava

Зачем использовать GUAVA

● Сэкономить значительное количество написанного кода

● Избежать написания кода, который трудно отлаживать и в котором легко ошибиться

● Улучшить читабельность● Улучшить скорость работы программы.

4

Page 5: Очень вкусный фрукт Guava

Особенность удаления фич● В отличие от JDK удаляют

нежелательное поведение через некоторое время

● @Beta API● @Deprecated non @Beta компоненты

удаляются через 18 месяцев

5

Page 6: Очень вкусный фрукт Guava

Базовые утилиты● Работа с null. Optional● Preconditions● Objects, toString, equals,

hashCode● Компараторы с Ordering

6

Page 7: Очень вкусный фрукт Guava

Использование и избежание работы с null

● null - источник множества ошибок.

● null быстр и нужно научится его правильно использовать, где это необходимо, и избегать во всех остальных случаях.

● Многие утилиты GUAVA где недопустимы null’ы бросают ошибку.

7

Page 8: Очень вкусный фрукт Guava

Optional<T>

null reference of T

Not null reference of T Present Optional<T>

Absent Optional<T>

8

Page 9: Очень вкусный фрукт Guava

Optional<T>методы создания

Optional.of(T)

Optional.absent()

Optional.fromNullable(T)

9

Page 10: Очень вкусный фрукт Guava

Optional<T>методы использования

boolean isPresent()

T get()

T or(T)

T orNull()

Set<T> asSet()10

Page 11: Очень вкусный фрукт Guava

Optional<T>. пример

private static Person nullPerson()

{

return null;

}

private static Person notNullPerson()

{

return new Person("Egor", "Chernyshev", 24);

}

11

Page 12: Очень вкусный фрукт Guava

Optional<T>. Пример

...

private static Person MARIA = new Person("Maria", "Petrova", 26);

...

Optional.of(nullPerson());// throws NullPointerExcepton

Optional.fromNullable(nullPerson()).or(MARIA); // Person{lastName=Petrova, firstName=Maria, age=26}

Optional.fromNullable(notNullPerson()).or(MARIA); // Person{lastName=Chernyshev, firstName=Egor, age=24}

Optional.fromNullable(nullPerson()).orNull(); // null

Optional.fromNullable(notNullPerson()).orNull();// Person{lastName=Chernyshev, firstName=Egor, age=24}

Optional.fromNullable(nullPerson()).asSet(); // []

Optional.fromNullable(notNullPerson()).asSet();// [Person{lastName=Chernyshev, firstName=Egor, age=24}]

Optional.absent().get();// throws IllegalStateException

...

12

Page 13: Очень вкусный фрукт Guava

Preconditions

13

Page 14: Очень вкусный фрукт Guava

Preconditions

...

import static com.google.common.base.Preconditions.checkArgument;

import static com.google.common.base.Preconditions.checkElementIndex;

import static com.google.common.base.Preconditions.checkNotNull;

import static com.google.common.base.Preconditions.checkPositionIndex;

import static com.google.common.base.Preconditions.checkPositionIndexes;

import static com.google.common.base.Preconditions.checkState;

...

14

Page 15: Очень вкусный фрукт Guava

Preconditions int positive = 1;

checkArgument(positive > 0, "Number %s must be a positive", positive); // IllegalArgumentException:

//Number 1 must be a negative

checkArgument(positive < 0, "Number %s must be a negative", positive); // IllegalArgumentException:

//Number 1 must be a negative

Object nullValue = null;

checkNotNull(nullValue, "Value mast be not null"); // NullPointerException: Value mast be not null

checkState(positive < 0); // IllegalStateException

checkElementIndex(5, 6);

checkElementIndex(6, 6); // IndexOutOfBoundsException: index (6) must be less than size (6)

checkPositionIndex(6, 6);

checkPositionIndexes(3, 4, 4);

15

Page 16: Очень вкусный фрукт Guava

Object Utilities.

equals, hashCode, toStringcompareTo

16

Page 17: Очень вкусный фрукт Guava

public class Person implements Comparable<Person>

{

private String firstName;

private String lastName;

private int age;

public Person(String firstName, String lastName, int age)

{

this.firstName = firstName;

this.lastName = lastName;

this.age = age;

}

getters and setters

...

}17

Page 18: Очень вкусный фрукт Guava

equals()...

@Override

public boolean equals(Object obj)

{

if (this == obj) return true;

if (obj == null) return false;

if (getClass() != obj.getClass()) return false;

Person other = (Person) obj;

return Objects.equals(lastName, other.lastName) &&

Objects.equals(firstName, other.firstName) &&

Objects.equals(age, other.age);

}

...18

Page 19: Очень вкусный фрукт Guava

hashCode()

...

@Override

public int hashCode()

{

return Objects.hash(lastName, firstName, age);

}

...

19

Page 20: Очень вкусный фрукт Guava

toString()...

@Override

public String toString()

{

return MoreObjects.toStringHelper(this)

.add("lastName", lastName)

.add("firstName", firstName)

.add("age", age)

.toString();

}

...

Person{lastName=Chernyshev, firstName=Egor, age=24}20

Page 21: Очень вкусный фрукт Guava

compareTo()...

@Override

public int compareTo(Person o)

{

return ComparisonChain.start()

.compare(lastName, o.lastName)

.compare(firstName, o.firstName)

.compare(age, o.age)

.result();

}

...

21

Page 22: Очень вкусный фрукт Guava

Ordering

утилита для работы с упорядоченными объектами

22

Page 23: Очень вкусный фрукт Guava

Ordering

● Ordering<T> - наследник Comparator<T>

● В Ordering реализованы методы использующие порядок: min, max, sort и т.д.

23

Page 24: Очень вкусный фрукт Guava

Ordering<T>. Создание ● Ordering.natural() - естественный порядок,

основанный на функции compare(T,T)● Ordering.usingToString() - лексикографический

порядок, строковых представлений (toString)● Ordering.from(Comparator)● Наследник Ordering

24

Page 25: Очень вкусный фрукт Guava

Ordering<T>. ИспользованиеgreatestOf(Iterable iterable, int k) See also: leastOf

isOrdered(Iterable)See also: isStricklyOrdered

sortedCopy(Iterable)See also: immutableSortedCopy

min(E, E)See also: max(E, E)

min(E, E, E, E...)See also: max(E, E, E, E...)

min(Iterable)See also: max(Iterable), min(Iterator), max(Iterator)

25

Page 26: Очень вкусный фрукт Guava

FirstName Ordering

private static Ordering<Person> FIRST_NAME_ORDERING =

Ordering.natural().nullsFirst().onResultOf(new Function<Person, String>()

{

@Override

public String apply(Person input)

{

return input.getFirstName();

}

});

26

Page 27: Очень вкусный фрукт Guava

Age Ordering

private static Ordering<Person> AGE_ORDERING =

Ordering.natural().onResultOf(new Function<Person, Integer>()

{

@Override

public Integer apply(Person input)

{

return input.getAge();

}

});

27

Page 28: Очень вкусный фрукт Guava

Список Person

private static List<Person> createPersonList()

{

return Lists.newArrayList(

new Person("Egor", "Chernyshev", 24),

new Person("Anton", "Borisov", 36),

new Person("Elena", "Petrova", 18),

new Person("Maxim", "Lobanov", 65),

new Person(null, "Alexandrova", 24));

}

28

Page 29: Очень вкусный фрукт Guava

List<Person> persons = createPersonList();

out.println("isOrdered =" + FIRST_NAME_ORDERING.isOrdered(persons)); // isOrdered =false

Collections.sort(persons, FIRST_NAME_ORDERING);

out.println(persons);// [Person{lastName=Alexandrova, firstName=null, age=24},

// Person{lastName=Borisov, firstName=Anton, age=36},

// Person{lastName=Chernyshev, firstName=Egor, age=24},

// Person{lastName=Petrova, firstName=Elena, age=18},

// Person{lastName=Lobanov, firstName=Maxim, age=65}]

out.println("isOrdered =" + FIRST_NAME_ORDERING.isOrdered(persons)); // isOrdered =true

out.println(AGE_ORDERING.max(persons)); // Person{lastName=Lobanov, firstName=Maxim, age=65}

out.println(AGE_ORDERING.min(persons)); // Person{lastName=Petrova, firstName=Elena, age=18}

Ordering<T>. Примеры

29

Page 30: Очень вкусный фрукт Guava

Ordering<T>. Примеры

Ordering<Person> compound = Ordering.compound(Lists.newArrayList(AGE_ORDERING,

FIRST_NAME_ORDERING));

List<Person> compoundSortedPersons = compound.sortedCopy(createPersonList());

out.println(compoundSortedPersons); // [Person{lastName=Petrova, firstName=Elena, age=18},

// Person{lastName=Alexandrova, firstName=null, age=24},

// Person{lastName=Chernyshev, firstName=Egor, age=24},

// Person{lastName=Borisov, firstName=Anton, age=36},

// Person{lastName=Lobanov, firstName=Maxim, age=65}]

30

Page 31: Очень вкусный фрукт Guava

GUAVA Collections

● ImmutableCollections● Новые коллекции в Guava● Утилитарные классы Sets, Lists, Maps…● Утилиты для расширения java коллекций31

Page 32: Очень вкусный фрукт Guava

Immutable Collections

32

Page 33: Очень вкусный фрукт Guava

Чем хороши Immutable objects?

● Безопасное использование в untrusted библиотеках.

● Потоко безопасны.● Хороши для хранения констант, так как

есть гарантия неизменяемости.

33

Page 34: Очень вкусный фрукт Guava

Interface JDK или Guava Immutable version

Collection JDK ImmutableCollection

List JDK ImmutableList

Set JDK ImmutableSet

SortedSet / NavigableSet

JDK ImmutableSortedSet

Map JDK ImmutableMap

SortedMap JDK ImmutableSortedMap

Multiset Guava ImmutableMultiset34

Page 35: Очень вкусный фрукт Guava

Interface JDK или Guava Immutable version

SortedMultiset Guava ImmutableSortedMultiset

Multimap Guava ImmutableMultimap

ListMultimap Guava ImmutableListMultimap

SetMultimap Guava ImmutableSetMultimap

BiMap Guava ImmutableSetMultimap

ClassToInstanceMap

Guava ImmutableClassToInstanceMap

Table Guava ImmutableTable35

Page 36: Очень вкусный фрукт Guava

ImmutableCollection. Создание

● ImmutableXXX.of● ImmutableXXX.copyOf● ImmutableXXX.builder()

36

Page 37: Очень вкусный фрукт Guava

ImmutableXXX.copyOf

ImmutableList<Person> GROUP = ImmutableList.of(

new Person("Egor", "Chernyshev", 24),

new Person("Anna", "Tarasova", 30));

ImmutableSet<String> ALPHABET = ImmutableSet.of("a", "b", "c");

ImmutableMap<String, Integer> CHAR_NUMBERS = ImmutableMap.of("a", 1, "b", 2);

ImmutableXXX.of

ImmutableList<Person> COPY_OF_GROUP = ImmutableList.copyOf(GROUP);

37

Page 38: Очень вкусный фрукт Guava

ImmutableXXX.builder()

ImmutableList<Person> GROUP_B = ImmutableList

.<Person>builder()

.addAll(GROUP)

.add(new Person("Anton", "Belov", 41))

.build();

38

Page 39: Очень вкусный фрукт Guava

copyOf умнее, чем вы думаете

● copyOf пытается избежать полного копирования объектов.

● В общем случае ImmutableXXX.copyOf(ImmutableXXX) пытается выполнится за O(1), за исключением некоторых случаев

39

Page 40: Очень вкусный фрукт Guava

исключения● ImmutableSet.copyOf(ImmutableList)

● ImmutableList<String> hugeList;

ImmutableList.copyOf(hugeList.subList(0, 10))

● ImmutableSet.copyOf (myImmutableSortedSet)

40

Page 41: Очень вкусный фрукт Guava

Multiset

41

Page 42: Очень вкусный фрукт Guava

Multiset

Мультимножество: {a, a, b, c, f, d}

Эквивалентность:{a, a, b} = {a, b, a}

42

Page 43: Очень вкусный фрукт Guava

Multiset. Пример

Multiset<Character> toCharsMultiset(String text)

{

return HashMultiset.create(Chars.asList(text.toCharArray()));

}

Подсчет количества каждого символа в тексте:

43

Page 44: Очень вкусный фрукт Guava

Multiset. РеализацииMap Соответствующий Multiset Допускает null?

HashMap HashMultiset Да

TreeMap TreeMultiset Да (если компаратор поддерживает)

LinkedHashMap LinkedHashMultiset Да

ConcurrentHashMap ConcurrentHashMultiset Нет

ImmutableMap ImmutableMultiset Нет

44

Page 45: Очень вкусный фрукт Guava

Multimap

45

Page 46: Очень вкусный фрукт Guava

Multimap

a->1, a->2, a->4, b->3, c->5или

a->[1, 2, 4], b->3, c->5

Map<K, List<V>> Map<K, Set<V>>

Multimap<K, V>

46

Page 47: Очень вкусный фрукт Guava

Multimap<K,V>. Представления

Multimap<K,V>.asMap() Map<K, Collection<V>>

Multimap<K,V>.entries() Collection<Entry<K,V>>

Multimap<K,V>.keySet() Set<K>

Multimap<K,V>.keys() Multiset<K>

Multimap<K,V>.values() Collection<V>

47

Page 48: Очень вкусный фрукт Guava

Multimap<K,V>. РеализацииРеализация Ключи ведут себя как... Значения ведут себя как...

ArrayListMultimap HashMap ArrayList

HashMultiMap HasMap HashSet

LinkedListMultimap LinkedHashMap LinkedList

LinkedHashMultiMap LinkedHashMap LinkedHashSet

TreeMultimap TreeMap TreeSet

ImmutableListMultimap ImmutableMap ImmutableList

ImmutableSetMultimap ImmutableMap ImmutableSet48

Page 49: Очень вкусный фрукт Guava

Multimap. Пример

private static Function<Person, String> FIRST_NAME_EXTRACTOR = new

Function<Person, String>()

{

@Override

public String apply(Person input)

{

return input.getFirstName();

}

};

49

Page 50: Очень вкусный фрукт Guava

Multimap. Пример List<Person> PERSONS = Lists.newArrayList(

new Person("Egor", "Chernyshev", 24),

new Person("Anton", "Borisov", 36),

new Person("Elena", "Petrova", 18),

new Person("Elena", "Birkova", 11),

new Person("Maxim", "Lobanov", 65));

Multimap<String, Person> index = Multimaps.index(PERSONS, FIRST_NAME_EXTRACTOR);

50

Page 51: Очень вкусный фрукт Guava

BiMap

51

Page 52: Очень вкусный фрукт Guava

BiMap<K,V>

BiMap<V, K> - это Map<K, V>, в которой

● Добавлен метод BiMap<V, K> inverse().

● Есть проверка на уникальность значений.

● values() возвращает Set<V>.52

Page 53: Очень вкусный фрукт Guava

BiMap<K,V>. РеализацииKey-Value Map Value-Key Map Реализация

HashMap HashMap HashBiMap

ImmutableMap ImmutableMap ImmutableBiMap

EnumMap EnumMap EnumBiMap

EnumMap HashMap EnumHashBiMap

53

Page 54: Очень вкусный фрукт Guava

Table

54

Page 55: Очень вкусный фрукт Guava

Table<R, C, V>

● Table - это способ хранения индекса объекта по двум ключам R и C.

● Table<R,C,V> заменяет неуклюжую реализацию структуры

Map<R, Map<C, V>>55

Page 56: Очень вкусный фрукт Guava

Table<R, C, V>. Представления

Table<R,C,V>.rowMap() Map<R, Map<C,V>>

Table<R,C,V>.rowKeySet() Set<R>

Table<R,C,V>.row(r) Map<C,V>

columnMap(), columnKeySet(), column(c)

Аналогично, row. Column access по производительности работает медленнее, чем row access из за структуры данных.

Table<R,C,V>.cellSet() Set<Table.Cell<R,C,V>>

56

Page 57: Очень вкусный фрукт Guava

Table<R, C, V>. РеализацииРеализация На основе структуры

HashBasedTable HashMap<R, HashMap<C, V>>

TreeBasedTable TreeMap<R, TreeMap<C, V>>

ImmutableTable ImmutableMap<R, ImmutableMap<C, V>>

ArrayTable Двумерный массив. Хорошо подходит для задач, с сильно заполненными таблицами.

57

Page 58: Очень вкусный фрукт Guava

ClassToInstanceMap

58

Page 59: Очень вкусный фрукт Guava

ClassToInstanceMap<B>

● Реализация Map<Class<? extends B>, B>● Поддерживает примитивы

Реализации:● ImmutableClassToInstanceMap● MutableClassToInstanceMap

59

Page 60: Очень вкусный фрукт Guava

public interface MegaService {}

public class SuperMegaService implements MegaService{}

public class SuperMegaBupperService implements MegaService{}

private static final ClassToInstanceMap<MegaService> REGISTRY = MutableClassToInstanceMap.create();

REGISTRY.putInstance(SuperMegaService.class, new SuperMegaService());// OK

REGISTRY.putInstance(SuperMegaBupperService.class, new SuperMegaBupperService());// OK

REGISTRY.putInstance(MegaService.class, new SuperMegaBupperService());// OK

REGISTRY.putInstance(SuperMegaService.class, new SuperMegaBupperService()); // Ошибка компиляции

REGISTRY.putInstance(String.class, "qqqq"); // Ошибка компиляции

REGISTRY.put(String.class, "qqqq"); // Ошибка компиляции

REGISTRY.getInstance(MegaService.class);// OK

REGISTRY.getInstance(String.class);// Ошибка компиляции

60

Page 61: Очень вкусный фрукт Guava

RangeSet

61

Page 62: Очень вкусный фрукт Guava

RangeSet<C extends Comparable>

RangeSet<Integer> rangeSet = TreeRangeSet.create();

rangeSet.add(Range.closed(1, 10)); // {[1, 10]}

rangeSet.add(Range.closedOpen(11, 15)); // disconnected range: {[1, 10], [11, 15)}

rangeSet.add(Range.closedOpen(15, 20)); // connected range; {[1, 10], [11, 20)}

rangeSet.add(Range.openClosed(0, 0)); // empty range; {[1, 10], [11, 20)}

rangeSet.remove(Range.open(5, 10)); // splits [1, 10]; {[1, 5], [10, 10], [11, 20)}

● JDK 1.6 +● Не поддерживается в GWT

62

Page 63: Очень вкусный фрукт Guava

RangeSet<C>. Представления

RangeSet<C>.subRangeSet(Range<C>) RangeSet<C>

RangeSet<C>.asRanges() Set<Range<C>>

RangeSet<C>.asSet(DiscreteDomain<C>)только ImmutableRangeSet

ImmutableSortedSet<C>

63

Page 64: Очень вкусный фрукт Guava

RangeSet<C>. ЗапросыМетод Возвращаемое значение

RangeSet<C>.contains(C) boolean

RangeSet<C>.rangeContaining(C) Range<C>

RangeSet<C>.encloses(Range<C>) boolean

RangeSet<C>.span() Range<C>

64

Page 65: Очень вкусный фрукт Guava

RangeMap

65

Page 66: Очень вкусный фрукт Guava

Collections UtilsКоллекция JDK или Guava Класс с утилитами

Collection JDK Collections2

List JDK Lists

Set JDK Sets

SortedSet JDK Sets

Map JDK Maps

SortedMap JDK Maps

Queue JDK Queues66

Page 67: Очень вкусный фрукт Guava

Collections UtilsКоллекция JDK или Guava Класс с утилитами

Multiset Guava Multisets

Multimap Guava Multimaps

BiMap Guava Maps

Table Guava Tables

67

Page 68: Очень вкусный фрукт Guava

Static constructors List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();

------------------------------------------------------------------------------------------

List<TypeThatsTooLongForItsOwnGood> list1 = Lists.newArrayList();

Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();

------------------------------------------------------------------------------------------

List<TypeThatsTooLongForItsOwnGood> list2 = new ArrayList<>();

------------------------------------------------------------------------------------------

Set<Type> copySet = Sets.newHashSet(elements);

List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");

------------------------------------------------------------------------------------------

List<Type> exactly100 = Lists.newArrayListWithCapacity(100);

List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);

Set<Type> approx100Set = Sets.newHashSetWithExpectedSize(100);

------------------------------------------------------------------------------------------

Multiset<String> multiset = HashMultiset.create();68

Page 69: Очень вкусный фрукт Guava

Iterables

● Guava предпочитает Iterable вместо Collection

● Многие Iterable являются Lazy● Утилита FluentItrable, оборачивает

Iterable и предоставляет набор методов для работы в функцинальном стиле.

69

Page 70: Очень вкусный фрукт Guava

Lists

Метод Описание

partiton(List, int) List<List> - разбиение списка на подсписки определенной длины.

reverse(List) Развернутое представление списка

70

Page 71: Очень вкусный фрукт Guava

Sets

Метод Описание

union(Set, Set) Объединение множеств

intersection(Set, Set) Пересечение

difference(Set, Set) Разность

symmetricDifference(Set, Set) симметричная разность

powerSet(Set) Множество всех подмножеств

71

Page 72: Очень вкусный фрукт Guava

Maps

72

Page 73: Очень вкусный фрукт Guava

Maps.uniqueIndex()Maps.uniqueIndex(Lists.newArrayList("dddd", "ddddd", "qwcccccde"), new Function<String, Integer>()

{

@Override

public Integer apply(String input)

{

return input.length();

}

});

//{4=dddd, 5=ddddd, 9=qwcccccde}

● Выбросится ошибка, если Function вернет неуникальное значение73

Page 74: Очень вкусный фрукт Guava

MapDifference d = Maps.difference()

entriesInCommon()entriesOnlyOnLeft() entriesOnlyOnRight()

entriesDiffering()74

Page 75: Очень вкусный фрукт Guava

Multimaps

Метод Описание

index(Iterable, Function) Построение индекса коллекции по ключевой функции

invertFrom(Multimap, Multimap) Разворот Map’ы (<K,V> -> <V,K>)

forMap(Map) Преобразвание Map<K,V> в Multimap<K,V>

75

Page 76: Очень вкусный фрукт Guava

Tables

Метод Описание

transpose(Table<R,C,V>) Транспонирование таблицы Table<R,C,V> -> Table<C,R,V>

76

Page 77: Очень вкусный фрукт Guava

Extention utilities

● Forwarding Decorators● PeekingIterator● AbstractIterator

77

Page 78: Очень вкусный фрукт Guava

Forwarding Decorators. Примерclass AddLoggingList<E> extends ForwardingList<E> {

final List<E> delegate; // backing list

@Override protected List<E> delegate() {

return delegate;

}

@Override public void add(int index, E elem) {

log(index, elem);

super.add(index, elem);

}

@Override public boolean add(E elem) {

return standardAdd(elem); // implements in terms of add(int, E)

}

@Override public boolean addAll(Collection<? extends E> c) {

return standardAddAll(c); // implements in terms of add

}

}

78

Page 79: Очень вкусный фрукт Guava

Forwarding DecoratorsInterface Forwarding decorator

Collection ForwardingCollection

List ForwardingList

Set ForwardingSet

SortedSet ForwardingSortedSet

Map ForwardingMap

SortedMap ForwardingSortedMap

ConcurrentMap ForwardingConcurrentMap

Map.Entry ForwardingMapEntry79

Page 80: Очень вкусный фрукт Guava

Interface Forwarding decorator

Queue ForwardingQueue

Iterator ForwardingIterator

ListIterator ForwardingListIterator

Multiset ForwardingSortedSet

Multimap ForwardingMultiset

ListMultiMap ForwardingListMultiMap

SetMultimap ForwardingSetMultimap

Forwarding Decorators

80

Page 81: Очень вкусный фрукт Guava

PeekingIterator

List<String> result = Lists.newArrayList();

PeekingIterator<String> iter = Iterators.peekingIterator(source.iterator());

while (iter.hasNext()) {

String current = iter.next();

while (iter.hasNext() && iter.peek().equals(current)) {

// skip this duplicate element

iter.next();

}

result.add(current);

}

81

Page 82: Очень вкусный фрукт Guava

AbstractIteratorpublic static Iterator<String> skipNulls(final Iterator<String> in) {

return new AbstractIterator<String>() {

protected String computeNext() {

while (in.hasNext()) {

String s = in.next();

if (s != null) {

return s;

}

}

return endOfData();

}

};

}82

Page 83: Очень вкусный фрукт Guava

CachesКэширование информации в памяти.

Применимость, создание кэшей, использование примеры.

83

Page 84: Очень вкусный фрукт Guava

Cache. Применимость

● Память -> Скорость

● Элемент используется больше 1 раза

● Все кэшируемые значения помещаются в оперативной памяти

84

Page 85: Очень вкусный фрукт Guava

Cache. Создание

Cache<String, Person> cache = CacheBuilder

.newBuilder()

.expireAfterAccess(5, TimeUnit.MINUTES)

.maximumSize(10000)

.build();

85

Page 86: Очень вкусный фрукт Guava

Cache. Добавление значенияCacheLoader

/**

* Медленная операция получения человека по Web сервису

* из внешней системы

*/

private Person loadPersonByWebService(String key)

{

return new Person("Anton", "Borisow", 88);

}

86

Page 87: Очень вкусный фрукт Guava

Cache. Добавление значенияCacheLoader

Cache<String, Person> cache = CacheBuilder

.newBuilder()

.expireAfterAccess(5, TimeUnit.MINUTES)

.maximumSize(10000)

.build(new CacheLoader<String, Person>()

{

@Override

public Person load(String key) throws Exception

{

return loadPersonByWebService(key);

}

});

87

Page 88: Очень вкусный фрукт Guava

Cache. Добавление значенияfrom Callable

try{

cache.get(key, new Callable<Person>(){

@Override

public Person call() throws Exception

{

return loadPersonByWebService(key);

}

});

}

catch (ExecutionException e)

{

throw new RuntimeException(e.getMessage(), e);

}88

Page 89: Очень вкусный фрукт Guava

Cache. Добавление значенияdirectly insert

cache.put(key, loadPersonByWebService(key));

89

Page 90: Очень вкусный фрукт Guava

Cache. Eviction

● Size-base eviction● Timed eviction● Reference-based eviction● Explicit eviction● Removal Listener

90

Page 91: Очень вкусный фрукт Guava

Cache. Size-based eviction

● CacheBulder.maximumSize(long)

● CacheBuilder.maximumWeight(long)

● CacheBuilder.weighter(Weighter<K,V>)

91

Page 92: Очень вкусный фрукт Guava

Cache. Timed eviction● CacheBuilder.expireAfterWrite(long, TimeUnit)

● CacheBuilder.expireAfterAccess(long, TimeUnit)

92

Page 93: Очень вкусный фрукт Guava

Cache. Reference-based eviction

● CacheBulder.weakKeys()

● CacheBuilder.weakValues()

● CacheBuilder.softValues()

93

Page 94: Очень вкусный фрукт Guava

Cache. Explicit removals

● Cache.invalidate(key)

● Cache.invalidateAll(keys)

● Cache.invalidateAll()

94

Page 95: Очень вкусный фрукт Guava

Cache. Когда происходит eviction

● В момент записи нового значения

● Иногда (если записей в кэш мало) при получении значения по ключу

● Кэш не обслуживается отдельным потоком!95

Page 96: Очень вкусный фрукт Guava

Cache. Прочие возможности

● Statistic:Включение: CacheBuilder.recordStats();Получение: CacheStats stats = Cache.stats();Использование:

● stats.hitRate() - количество попаданий● stats.averageLoadPenalty() - среднее время на загрузку

новых значений● stats.evictionCount() - количество eviction’ов

● asMap96

Page 97: Очень вкусный фрукт Guava

Мощные, простые инструменты для написания корректного

многопоточного кода

ListenableFutures, Service, Striped

97

Page 98: Очень вкусный фрукт Guava

ListenableFuture

● Расширяет Future - позволяет регистрировать Callback на момент выполнения операции.

● Callback будет вызван один раз.● Callback обрабатывает ошибки с

помщью onFaiture() метода.98

Page 99: Очень вкусный фрукт Guava

DocumentLoaderService

private ListeningExecutorService executorService = MoreExecutors

.listeningDecorator(Executors.newFixedThreadPool(5));

public void loadDocument(final String docUrl, FutureCallback<String> callback){

ListenableFuture<String> future = executorService.submit(new Callable<String>(){

@Override

public String call() throws Exception{

return IOUtils.toString(docUrl, StandardCharsets.UTF_8.name());

}

});

Futures.addCallback(future, callback);

}

… 99

Page 100: Очень вкусный фрукт Guava

DocumentLoaderService service = DocumentLoaderService.instance();

for (String url : TESTED_URLS)

{

service.loadDocument(url, new FutureCallback<String>(){

@Override

public void onSuccess(String result){

handleDocument(result);

}

@Override

public void onFailure(Throwable t){

handleError(t);

}

});

}

DocumentLoaderService. Использование

100

Page 101: Очень вкусный фрукт Guava

Service

101

Page 102: Очень вкусный фрукт Guava

Service

● Интерфейс Service - это объект с рабочим состоянием и методами остановки и запуска.

● Service имеет ряд предопределенных состояний.

● Существуют базовые абстрактные реализации, которые необходимо переопределять для написания собственных служб и сервисов.102

Page 103: Очень вкусный фрукт Guava

Использование Service

NEW STARTING RUNNING STOPPING TERMINATED

Метод Описание

startAsync() Запуск

stopAsync() Остановка

state() Статус103

Page 104: Очень вкусный фрукт Guava

Serivce. Базовые реализации

● AbstractIdleService● AbstractExecutionThreadService● AbstractScheduledService● AbstractService

104

Page 105: Очень вкусный фрукт Guava

ServiceMangerМетод Описание

startAsync() Стартует все службы

stopAsync() Останавливает все службы

addListener Добавление листенеров на смены статусов

awaitHealthy() дождаться пока все службы не станут RUNNING

awaitStopped() дождаться пока все службы не будут остановлены

isHealthy() true, если все службы RUNNING

servicesByState() ultimap сервисов сгрупированных по состояниям

startupTimes() Map сервисов с временами старта. Отсортированная105

Page 106: Очень вкусный фрукт Guava

Striped

106

Page 107: Очень вкусный фрукт Guava

Striped. Пример private Lock lock = new ReentrantLock();

public void runAction(String key)

{

lock.lock();

try

{

threadSafeActionWithResource(getResource(key));

}

finally

{

lock.unlock();

}

}107

Page 108: Очень вкусный фрукт Guava

Striped. Пример private Striped<Lock> striped = Striped.lazyWeakLock(2);

public void runAction(String key)

{

Lock lock = striped.get(key);

lock.lock();

try

{

threadSafeActionWithResource(getResource(key));

}

finally

{

lock.unlock();

}

}

108

Page 109: Очень вкусный фрукт Guava

Прочие утилитыStrings, Joiner, Splitter, CharMatcher

и пр.

109

Page 110: Очень вкусный фрукт Guava

Strings

Метод Описание

isNullOrEmpty(str) true,если str == null или str.length() == 0

nullToEmpty(str) Преобразуется null в “”

emptyToNull(str) Преобразует “” в null

repeat(str, int) Повторяет str строку int раз

110

Page 111: Очень вкусный фрукт Guava

Joiner

Joiner joiner = Joiner.on(", ").useForNull("null");

List<String> parts = Lists.newArrayList("alpha", "beta", "gamma");

parts.add(null);

String joined = joiner.join(parts);

// alpha, beta, gamma, null

111

Page 112: Очень вкусный фрукт Guava

Splitter

Iterable<String> splited = Splitter

.on(",")

.omitEmptyStrings()

.split("aa,,ddd,,bb,b,bbbb,ffd");

//[aa, ddd, bb, b, bbbb, ffd]

112

Page 113: Очень вкусный фрукт Guava

CharMatcher

113

Page 114: Очень вкусный фрукт Guava

PrimitivesПримитивный тип Утилиты

byte Bytes, SignedBytes, UnsignedBytes

short Shorts

int Ints, UnsignedInteger, UnsignedInts

long Longs, UnsignedLong, UnsignedLongs

float Floats

double Doubles

char Chars

boolean Booleans114

Page 115: Очень вкусный фрукт Guava

Ranges

115

Page 116: Очень вкусный фрукт Guava

MathIntMath, LongMath, BigIntegerMath

116

Page 117: Очень вкусный фрукт Guava

Hashing

● md5● sha256● sha1● sha512● murmur2_128● murmur3_32

117

Page 118: Очень вкусный фрукт Guava

Вопросы?

Егор Чернышев

email: [email protected]

Skype: egrik1990