Google Guava v07范例

我们在TouK举办了一个名为“每周技术研讨会”的活动,即每个星期五的16:00,每个愿意参加的人都有一个演讲。 我们展示了我们在家学习和学习的东西,但是我们也设有一个公告板,上面有人们想听的话题。 上周MaciejPróchniak谈论了Clojure ,这次有几个人要求介绍Google Guava库 。

由于这是一项艰巨而简单的任务,所以我很乐意交付。

WTF是番石榴吗?

这是一组非常简单的基本类,您最终还是要自己编写。 仅由Google来思考Apache的共同点。 只是为了让您的生活更轻松一点。

Wiktor Gworek在Javarsowia 2010上做了一个早期(v04) 演讲 ,另外一个是波兰语演讲 。

在撰写本文时,最新版本是v07,已经过Mavenized,可以在公共Maven repo上找到 。

这是一些有趣的事情的快速回顾。 不过,不要期望任何花哨的东西,Guava非常基础。

@VisibleForTesting

一个简单的注释,告诉您为什么放宽了特定的属性访问限制。

在测试中使用的一个常见技巧是放宽对特定属性的默认访问限制,以便您可以在单元测试中使用它,该单元测试位于相同的程序包中(尽管在不同的目录中)。 无论是好是坏,请记住给开发人员一个提示。

考虑:

public class User {
    private Long id;
    private String firstName;
    private String lastName;
    String login;

为什么登录程序包有作用域?

public class User {
    private Long id;
    private String firstName;
    private String lastName;
    @VisibleForTesting String login;

啊,那是为什么。

前提条件

Guava有一些防御性编程的先决条件(按合同设计),但不如Apache Commons / Spring框架具备的条件好。 有趣的一件事是Guava解决方案返回了对象,因此可以进行内联。 考虑:

使用手写的前提条件:

public User(Long id, String firstName, String lastName, String login) {
        validateParameters(id, firstName, lastName, login);
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.login = login.toLowerCase();
    }

    private void validateParameters(Long id, String firstName, String lastName, String login) {
        if(id == null ) {
            throw new IllegalArgumentException('id cannot be null');
        }

        if(firstName == null || firstName.length() == 0) {
            throw new IllegalArgumentException('firstName cannot be empty');
        }

        if(lastName == null || lastName.length() == 0) {
            throw new IllegalArgumentException('lastName cannot be empty');
        }

        if(login == null || login.length() == 0) {
            throw new IllegalArgumentException('login cannot be empty');
        }
    }

使用番石榴先决条件:

public void fullyImplementedGuavaConstructorWouldBe(Long id, String firstName, String lastName, String login) {
        this.id = checkNotNull(id);
        this.firstName = checkNotNull(firstName);
        this.lastName = checkNotNull(lastName);
        this.login = checkNotNull(login);

        checkArgument(firstName.length() > 0);
        checkArgument(lastName.length() > 0);
        checkArgument(login.length() > 0);
    }

(感谢Yom注意到checkNotNull必须在checkArgument之前进行,尽管这有点不直观)

使用spring或apache commons前提(两个库的用法看起来完全一样):

public void springConstructorWouldBe(Long id, String firstName, String lastName, String login) {
        notNull(id); hasText(firstName); hasText(lastName); hasText(login);
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.login = login;
    }

CharMatcher

对于讨厌regexp或只想要简单美观的对象样式模式匹配解决方案的人。

例子:

和/或易用性

String input = 'This invoice has an id of 192/10/10';
        CharMatcher charMatcher = CharMatcher.DIGIT.or(CharMatcher.is('/'));
        String output = charMatcher.retainFrom(input);

输出是:192/10/10

否定:

String input = 'DO NOT scream at me!';
        CharMatcher charMatcher = CharMatcher.JAVA_LOWER_CASE.or(CharMatcher.WHITESPACE).negate();
        String output = charMatcher.retainFrom(input);

输出是:DONOT!

范围:

String input = 'DO NOT scream at me!';
        CharMatcher charMatcher = CharMatcher.inRange('m', 's').or(CharMatcher.is('a').or(CharMatcher.WHITESPACE));
        String output = charMatcher.retainFrom(input);

输出是:sram am

细木工/分离器

顾名思义,它是正确完成字符串连接/拆分的方法,尽管我发现调用有点儿反转了……哦,那是java。

String[] fantasyGenres = {'Space Opera', 'Horror', 'Magic realism', 'Religion'};
        String joined = Joiner.on(', ').join(fantasyGenres);

输出:太空歌剧,恐怖片,魔幻现实主义,宗教

您可以跳过空值:

String[] fantasyGenres = {'Space Opera', null, 'Horror', 'Magic realism', null, 'Religion'};
        String joined = Joiner.on(', ').skipNulls().join(fantasyGenres);

输出:太空歌剧,恐怖片,魔幻现实主义,宗教

您可以填写空值:

String[] fantasyGenres = {'Space Opera', null, 'Horror', 'Magic realism', null, 'Religion'};
        String joined = Joiner.on(', ').useForNull('NULL!!!').join(fantasyGenres);

输出:太空歌剧,NULL !!!,恐怖,魔术现实主义,NULL !!!,宗教

您可以加入地图

Map map = newHashMap();
        map.put(1, 'Space Opera');
        map.put(2, 'Horror');
        map.put(3, 'Magic realism');
        String joined = Joiner.on(', ').withKeyValueSeparator(' -> ').join(map);

输出:1? 太空歌剧2 恐怖3? 魔幻现实主义

Split返回Iterable而不是JDK数组:

String input = 'Some very stupid data with ids of invoces like 121432, 3436534 and 8989898 inside';
        Iterable splitted = Splitter.on(' ').split(input);

尽管您不能为每个“列”指定不同的长度,但Split会进行固定长度的拆分,这使得在解析某些导出效果不佳的Excel时,它的使用受到了限制。

String input =
                'A  1  1  1  1\n' +
                'B  1  2  2  2\n' +
                'C  1  2  3  3\n' +
                'D  1  2  5  3\n' +
                'E  3  2  5  4\n' +
                'F  3  3  7  5\n' +
                'G  3  3  7  5\n' +
                'H  3  3  9  7';
        Iterable splitted = Splitter.fixedLength(3).trimResults().split(input);

您可以在拆分时使用CharMatcher

String input = 'Some very stupid data with ids of invoces like 123231/fv/10/2010, 123231/fv/10/2010 and 123231/fv/10/2010';
        Iterable splitted = Splitter.on(CharMatcher.DIGIT.negate())
                                            .trimResults()
                                            .omitEmptyStrings()
                                            .split(input);

谓词/函数

谓词本身并不多,它只是一个带有返回true的方法的接口,但是如果将谓词与函数和Collections2(一个简化了集合处理的番石榴类)结合使用,则可以在工具箱中找到一个不错的工具。

但是,让我们从基本谓词使用开始。 假设我们要查找是否有用数字登录的用户。 接种将是(返回布尔值):

Predicates.in(users).apply(shouldNotHaveDigitsInLoginPredicate);

谓词看起来像那样

public class ShouldNotHaveDigitsInLoginPredicate implements Predicate {
    @Override
    public boolean apply(User user) {
        checkNotNull(user);
        return CharMatcher.DIGIT.retainFrom(user.login).length() == 0;
    }    
}

现在让我们添加一个函数,该函数会将用户转换为他的全名:

public class FullNameFunction implements Function {
    @Override
    public String apply(User user) {
        checkNotNull(user);
        return user.getFirstName() + ' ' + user.getLastName();
    }    
}

您可以使用静态方法转换调用它:

List users = newArrayList(new User(1L, 'sylwek', 'stall', 'rambo'),
  new User(2L, 'arnold', 'schwartz', 'commando'));

List fullNames = transform(users, new FullNameFunction());

现在,让谓词与函数结合使用,以打印登录名不包含数字的用户名:

List users = newArrayList(new User(1L, 'sylwek', 'stall', 'rambo'), 
  new User(2L, 'arnold', 'schwartz', 'commando'), 
  new User(3L, 'hans', 'kloss', 'jw23'));

Collection usersWithoutDigitsInLogin = filter(users, new ShouldNotHaveDigitsInLoginPredicate());
String names = Joiner.on('\n').join( transform(usersWithoutDigitsInLogin, new FullNameFunction()) );

我们没有得到的是: 折叠(减少)和元组 。 哦,好吧,如果您想使用Java中的函数 ,您可能还是会转向Java Functional Library ,对吧?

案例格式

是否曾经想过用一个衬里将这些丑陋的PHP Pear名称转换为漂亮的java / cpp样式? 没有? 好吧,无论如何,您可以:

String pearPhpName = 'Really_Fucked_Up_PHP_PearConvention_That_Looks_UGLY_because_of_no_NAMESPACES';
String javaAndCPPName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL , pearPhpName);

输出:ReallyFuckedUpPhpPearconventionThatLooksUglyBecauseOfNoNamespaces

但是,由于Oracle接管了Sun,您实际上可能希望将其转换为sql风格,对吗?

String sqlName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, javaAndCPPName);

输出:real_fucked_up_php_pearconvention_that_looks_ugly_because_of_no_namespaces

馆藏

番石榴具有Google集合库1.0的超集,这确实是将这种依赖关系包含在pom中的一个很好的理由。 我什至不会尝试描述所有功能,而只是指出一些不错的东西:

  • 您几乎拥有所有东西的不可变版本
  • 您可以在常见类型(如列表,集合,地图,对象数组)上获得一些不错的静态和静态类型化方法,这些方法包括:
    • 基于返回类型创建的简单方法:例如newArrayList
    • 转换(应用返回不可变版本的函数的方式)
    • 分区(分页)
    • 逆转

现在还有更多有趣的收藏。

多图

Mutlimap基本上是一个映射,单个键可以具有许多值。 是否曾经在您的代码中创建Map >? 您不再需要了。

Multimap multimap = HashMultimap.create();
        multimap.put(1, 'a');
        multimap.put(2, 'b');
        multimap.put(3, 'c');
        multimap.put(1, 'a2');

当然也有不可变的实现:ImmutableListMultimap,ImmutableSetMultomap等。

您可以在线(最多5个元素)或使用构建器构造不可变项:

Multimap multimap = ImmutableSetMultimap.of(1, 'a', 2, 'b', 3, 'c', 1, 'a2'); 
Multimap multimap = new ImmutableSetMultimap.Builder()
        .put(1, 'a')
        .put(2, 'b')
        .put(3, 'c')
        .put(1, 'a2')
        .build();

双图

BiMap是仅具有唯一值的地图。 考虑一下:

@Test(expected = IllegalArgumentException.class)
public void biMapShouldOnlyHaveUniqueValues() {
 BiMap biMap = HashBiMap.create();
 biMap.put(1, 'a');
 biMap.put(2, 'b');
 biMap.put(3, 'a'); //argh! an exception
}

这使您可以反转地图,因此值成为关键,反之亦然:

BiMap biMap = HashBiMap.create();
biMap.put(1, 'a');
biMap.put(2, 'b');
biMap.put(3, 'c');

BiMap invertedMap = biMap.inverse();

不知道我实际上想用它做什么。

约束条件

这使您可以在集合上添加约束检查,以便仅添加通过约束的值。

想象一下,我们想要一个在他们的登录名中带有首字母“ r”的用户集合。

Constraint loginMustStartWithR = new Constraint() {
    @Override
    public User checkElement(User user) {
        checkNotNull(user);
        
        if(!user.login.startsWith('r')) {
            throw new IllegalArgumentException('GTFO, you are not Rrrrrrrrr');
        }

        return user;
    }
};

现在进行测试:

@Test(expected = IllegalArgumentException.class)
public void shouldConstraintCollection() {
 //given
 Collection users = newArrayList(new User(1L, 'john', 'rambo', 'rambo'));
 Collection usersThatStartWithR = constrainedCollection(users, loginMustStartWithR);

 //when
 usersThatStartWithR.add(new User(2L, 'arnold', 'schwarz', 'commando'));
}

您还可以立即获得notNull约束:

//notice it's not an IllegalArgumentException :( 
@Test(expected = NullPointerException.class)
public void notNullConstraintShouldWork() {
 //given
 Collection users = newArrayList(1);
 Collection notNullCollection = constrainedCollection(users, notNull());

 //when
 notNullCollection.add(null);
}

需要记住的事情:约束条件不是检查集合中已经存在的数据。

桌子

正如预期的那样,表是具有列,行和值的集合。 我猜没有更多的Map >。 用法很简单,您可以转置:

Table table = HashBasedTable.create();
table.put(1, 'a', '1a');
table.put(1, 'b', '1b');
table.put(2, 'a', '2a');
table.put(2, 'b', '2b');

Table transponedTable = Tables.transpose(table);

就是这样,伙计们。 我没有介绍util.concurrent,原语,io和net软件包,但您可能已经知道会发生什么。

祝您编程愉快,别忘了分享!

参考: Solid Craft博客上来自JCG合作伙伴 Jakub Nabrdalik的Google Guava v07示例 。


翻译自: https://www.javacodegeeks.com/2012/10/google-guava-v07-examples.html

你可能感兴趣的:(java,python,spring,编程语言,大数据)