《Google Guava 官方教程》阅读笔记

一。使用和避免null

创建:

public void test1(){
        String a = "5";
        String b = null;

        // 创建空的Optional对象,注意o5不是null
        Optional<Object> o5 = Optional.absent();
        System.out.println(o5.isPresent());

        // 创建Optional,o2报NullPointerException异常,不接受null对象
        Optional<String> o1 = Optional.of(a);
        Optional<String> o2 = Optional.of(b);

        // 创建Optional,允许null对象
        Optional<String> o3 = Optional.fromNullable(a);
        Optional<String> o4 = Optional.fromNullable(b);
}

2.常用方法

@org.junit.Test
    public void test1() {
        String a = "5";
        Optional<String> o1 = Optional.of(a);
        System.out.println(o1.isPresent());
        System.out.println(o1.get());
        System.out.println(o1.orNull());
        System.out.println(o1.toJavaUtil());
    }

输出:
true
5
5
Optional[5]
二。前置条件

静态导入,和普通的引包一样,语法是import static XXX.静态类名,使用静态导入后,再使用静态类下的方法就可以直接通过方法名调用了

Preconditions里面的方法:

  1 .checkArgument(boolean) :
  功能描述:检查boolean是否为真。 用作方法中检查参数
  失败时抛出的异常类型: IllegalArgumentException

  2.checkNotNull(T):     
  功能描述:检查value不为null, 直接返回value;
  失败时抛出的异常类型:NullPointerException

  3.checkState(boolean):
  功能描述:检查对象的一些状态,不依赖方法参数。 例如, Iterator可以用来next是否在remove之前被调用。
  失败时抛出的异常类型:IllegalStateException

  4.checkElementIndex(int index, int size):
  功能描述:检查index是否为在一个长度为size的list, string或array合法的范围。 index的范围区间是[0, size)(包含0不包含size)。无需直接传入list, string或array, 只需传入大小。返回index。  
  失败时抛出的异常类型:IndexOutOfBoundsException


  5.checkPositionIndex(int index, int size):
  功能描述:检查位置index是否为在一个长度为size的list, string或array合法的范围。 index的范围区间是[0, size)(包含0不包含size)。无需直接传入list, string或array, 只需传入大小。返回index。
  失败时抛出的异常类型:IndexOutOfBoundsException

  6.checkPositionIndexes(int start, int end, int size):
  功能描述:检查[start, end)是一个长度为size的list, string或array合法的范围子集。伴随着错误信息。
  失败时抛出的异常类型:IndexOutOfBoundsException

 

public class PreconditionsTest {

    @Test
    public void testPreconditions() throws Exception {

        getPerson(8, "peida"); // 正确的情况
        getPerson(-9, "peida"); // age不满足条件的情况
        // getPerson(8, null);// name不满足条件的地方
    }

    /**
     * 
     * @param age
     *            age应该满足age>0的条件
     * @param neme
     *            name应该满足,name!=null的条件
     * @throws Exception
     * @return: void
     */
    public static void getPerson(int age, String name) throws Exception {
        // 对于age合法性的检查
        Preconditions.checkArgument(age > 0, " age 应该满足 age > 0  的条件,age现在的数值为  ", age);
        // 对于name的合法性检查
        Preconditions.checkNotNull(name, "name 应该满足 name !=null 的条件,name现在的数值为", name);
    }
}
方法声明(不包括额外参数)描述检查失败时抛出的异常
checkArgument(boolean)检查 boolean 是否为 true,用来检查传递给方法的参数。IllegalArgumentException
checkNotNull(T)检查 value 是否为 null,该方法直接返回 value,因此可以内嵌使用 checkNotNull。NullPointerException
checkState(boolean)用来检查对象的某些状态。IllegalStateException
checkElementIndex(int index, int size)检查 index 作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size *IndexOutOfBoundsException
checkPositionIndex(int index, int size)检查 index 作为位置值对某个列表、字符串或数组是否有效。index>=0 && index<=size *IndexOutOfBoundsException
checkPositionIndexes(int start, int end, int size)检查[start, end]表示的位置范围对某个列表、字符串或数组是否有效*IndexOutOfBoundsException

 三。常见的object方法

equals:

当一个对象中的字段可以为 null 时,实现 Object.equals 方法会很痛苦,因为不得不分别对它们进行 null 检查。使用 Objects.equal 帮助你执行 null 敏感的 equals 判断,从而避免抛出 NullPointerException。例如:


    Objects.equal("a", "a"); // returns true
    Objects.equal(null, "a"); // returns false
    Objects.equal("a", null); // returns false
    Objects.equal(null, null); // returns true

注意:JDK7 引入的 Objects 类提供了一样的方法 Objects.equals

hashCode

用对象的所有字段作散列[hash]运算应当更简单。Guava 的 Objects.hashCode(Object...)会对传入的字段序列计算出合理的、顺序敏感的散列值。你可以使用 Objects.hashCode(field1, field2, …, fieldn)来代替手动计算散列值。

注意:JDK7 引入的 Objects 类提供了一样的方法 Objects.hash(Object...)

toString

好的 toString 方法在调试时是无价之宝,但是编写 toString 方法有时候却很痛苦。使用 Objects.toStringHelper 可以轻松编写有用的 toString 方法。例如


    // Returns "ClassName{x=1}"
    Objects.toStringHelper(this).add("x", 1).toString();
    // Returns "MyObject{x=1}"
    Objects.toStringHelper("MyObject").add("x", 1).toString();

compare/compareTo

实现一个比较器[Comparator],或者直接实现 Comparable 接口有时也伤不起。考虑一下这种情况:


    class Person implements Comparable<Person> {
      private String lastName;
      private String firstName;
      private int zipCode;

      public int compareTo(Person other) {
        int cmp = lastName.compareTo(other.lastName);
        if (cmp != 0) {
          return cmp;
        }
        cmp = firstName.compareTo(other.firstName);
        if (cmp != 0) {
          return cmp;
        }
        return Integer.compare(zipCode, other.zipCode);
      }
    }

这部分代码太琐碎了,因此很容易搞乱,也很难调试。我们应该能把这种代码变得更优雅,为此,Guava 提供了 ComparisonChain

ComparisonChain 执行一种懒比较:它执行比较操作直至发现非零的结果,在那之后的比较输入将被忽略。


    public int compareTo(Foo that) {
    return ComparisonChain.start()
            .compare(this.aString, that.aString)
            .compare(this.anInt, that.anInt)
            .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
            .result();
    }

四。排序: Guava 强大的”流畅风格比较器”

创建排序器:常见的排序器可以由下面的静态方法创建

方法描述
natural()对可排序类型做自然排序,如数字按大小,日期按先后排序
usingToString()按对象的字符串形式做字典排序[lexicographical ordering]
from(Comparator)把给定的 Comparator 转化为排序器

 

 @org.junit.Test
    public void test1() {
        User u1 = new User(1,1);
        User u2 = new User(2,1);

        Ordering<User> byLengthOrdering = new Ordering<User>() {
            public int compare(User u1, User u2) {
                return Ints.compare(u1.a, u2.a);
            }
        };

        int compare = byLengthOrdering.compare(u1, u2);
        System.out.println(compare);
    }

链式调用方法:通过链式调用,可以由给定的排序器衍生出其它排序器

方法描述
reverse()获取语义相反的排序器
nullsFirst()使用当前排序器,但额外把 null 值排到最前面。
nullsLast()使用当前排序器,但额外把 null 值排到最后面。
compound(Comparator)合成另一个比较器,以处理当前排序器中的相等情况。
lexicographical()基于处理类型 T 的排序器,返回该类型的可迭代对象 Iterable<T>的排序器。
onResultOf(Function)对集合中元素调用 Function,再按返回值用当前排序器排序。

    Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(new Function<Foo, String>() {
      public String apply(Foo foo) {
        return foo.sortedBy;
      }
    });

运用排序器:Guava 的排序器实现有若干操纵集合或元素值的方法

方法描述另请参见
greatestOf(Iterable iterable, int k)获取可迭代对象中最大的k个元素。leastOf
isOrdered(Iterable)判断可迭代对象是否已按排序器排序:允许有排序值相等的元素。isStrictlyOrdered
sortedCopy(Iterable)判断可迭代对象是否已严格按排序器排序:不允许排序值相等的元素。immutableSortedCopy
min(E, E)返回两个参数中最小的那个。如果相等,则返回第一个参数。max(E, E)
min(E, E, E, E...)返回多个参数中最小的那个。如果有超过一个参数都最小,则返回第一个最小的参数。max(E, E, E, E...)
min(Iterable)返回迭代器中最小的元素。如果可迭代对象中没有元素,则抛出 NoSuchElementException。max(Iterable), min(Iterator), max(Iterator)
Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(sortKeyFunction)

 

不可变集合

 public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
            "red",
            "orange",
            "yellow",
            "green",
            "blue",
            "purple");

为什么要使用不可变集合

不可变对象有很多优点,包括:

  • 当对象被不可信的库调用时,不可变形式是安全的;
  • 不可变对象被多个线程调用时,不存在竞态条件问题
  • 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);
  • 不可变对象因为有固定不变,可以作为常量来安全使用。

创建对象的不可变拷贝是一项很好的防御性编程技巧。Guava 为所有 JDK 标准集合类型和 Guava 新集合类型都提供了简单易用的不可变版本。

JDK 也提供了 Collections.unmodifiableXXX 方法把集合包装为不可变形式,但我们认为不够好:

  • 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景;
  • 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;
  • 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。

不可变集合可以用如下多种方式创建:

  • copyOf 方法,如 ImmutableSet.copyOf(set);
  • of 方法,如 ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
  • Builder 工具,如

    public static final ImmutableSet<Color> GOOGLE_COLORS =
            ImmutableSet.<Color>builder()
                .addAll(WEBSAFE_COLORS)
                .add(new Color(0, 191, 255))
                .build();

 

@org.junit.Test
    public void test1() {
        List<Integer> integers = Arrays.asList(1, 2, 3);
        ImmutableList<Integer> integers1 = ImmutableList.copyOf(integers);

        System.out.println(integers1);
    }

细节:关联可变集合和不可变集合

可变集合接口属于JDK还是Guava不可变版本
CollectionJDKImmutableCollection
ListJDKImmutableList
SetJDKImmutableSet
SortedSet/NavigableSetJDKImmutableSortedSet
MapJDKImmutableMap
SortedMapJDKImmutableSortedMap
MultisetGuavaImmutableMultiset
SortedMultisetGuavaImmutableSortedMultiset
MultimapGuavaImmutableMultimap
ListMultimapGuavaImmutableListMultimap
SetMultimapGuavaImmutableSetMultimap
BiMapGuavaImmutableBiMap
ClassToInstanceMapGuavaImmutableClassToInstanceMap
TableGuavaImmutableTable

Guava 提供了一个新集合类型 Multiset,它可以多次添加相等的元素。维基百科从数学角度这样定义 Multiset:”集合[set]概念的延伸,它的元素可以重复出现…与集合[set]相同而与元组[tuple]相反的是,Multiset 元素的顺序是无关紧要的:Multiset {a, a, b}和{a, b, a}是相等的”。——译者注:这里所说的集合[set]是数学上的概念,Multiset继承自 JDK 中的 Collection 接口,而不是 Set 接口,所以包含重复元素并没有违反原有的接口契约。

@org.junit.Test
    public void test1() {
        String strWorld="a|b|c|d|e|a|a";
        String[] words=strWorld.split("\\|");
        List<String> wordList=new ArrayList<String>();
        for (String word : words) {
            wordList.add(word);
        }
        System.out.println(wordList.toString());

        Multiset<String> wordsMultiset = HashMultiset.create();
        wordsMultiset.addAll(wordList);
        System.out.println(wordsMultiset.toString());

        for(String key:wordsMultiset.elementSet()){
            System.out.println(key+" count:"+wordsMultiset.count(key));
        }
    }

输出:
[a, b, c, d, e, a, a]
[a x 3, b, c, d, e]
a count:3
b count:1
c count:1
d count:1
e count:1

Multiset主要方法

  Multiset接口定义的接口主要有:
    add(E element) :向其中添加单个元素
    add(E element,int occurrences) : 向其中添加指定个数的元素
    count(Object element) : 返回给定参数元素的个数
    remove(E element) : 移除一个元素,其count值 会响应减少
    remove(E element,int occurrences): 移除相应个数的元素
    elementSet() : 将不同的元素放入一个Set中
    entrySet(): 类似与Map.entrySet 返回Set<Multiset.Entry>。包含的Entry支持使用getElement()和getCount()
    setCount(E element ,int count): 设定某一个元素的重复次数
    setCount(E element,int oldCount,int newCount): 将符合原有重复个数的元素修改为新的重复次数
    retainAll(Collection c) : 保留出现在给定集合参数的所有的元素
    removeAll(Collectionc) : 去除出现给给定集合参数的所有的元素

一篇详细的guava教程:http://www.bjpowernode.com/tutorial_guava/743.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

一篇很好的学习笔记:https://www.cnblogs.com/peida/tag/Guava%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值