分类 结绳记事 下的文章

JDK8新特性之Stream流


是什么是Stream流

java.util.stream.Stream

Stream流和传统的IO流,它们都叫流,却是两个完全不一样的概念和东西。

流可以简单的说是处理数据集合的东西,可以申明式流式API来处理集合,而不是写一个逻辑实现。
流分类
流分为顺序流及并行流,顺序流即每个指令按顺序执行,并行流即集合里面的操作并行执行。

List<Integer> numbers = Arrays.asList(1, 2, 3);
// 顺序流
numbers.stream().forEach(n -> System.out.print(n));
//并行流
numbers.parallelStream().forEach(n -> System.out.print(n));

以上例子,顺序流总是输出123,而并行流则每次结果都不一定,并行流使用了ForkJoinPool分而治之
使用流
以下举了流的一些常用的用法。

public class StreamTest {

public static void main(String[] args) {
    System.out.println("过滤-找出年纪大于18岁的人");
    List<User> list = initList();
    list.stream().filter((User user) -> user.getAge() > 18).collect(Collectors.toList())
            .forEach(System.out::println);
    System.out.println();

    System.out.println("最大值-找出最大年纪的人");
    list = initList();
    Optional<User> max = list.stream().max((u1, u2) -> u1.getAge() - u2.getAge());
    System.out.println(max.get());
    System.out.println();

    System.out.println("映射-规纳-求所有人的年纪总和");
    list = initList();
    Optional<Integer> reduce = list.stream().map(User::getAge).reduce(Integer::sum);
    System.out.println(reduce.get());
    System.out.println();

    System.out.println("分组-按年纪分组");
    list = initList();
    Map<Integer, List<User>> userMap = list.stream()
            .collect(Collectors.groupingBy(User::getAge));
    MapUtils.verbosePrint(System.out, null, userMap);
    System.out.println();

    System.out.println("创建-去重-统计");
    Stream<User> userStream = Stream
            .of(new User("u1", 1), new User("u2", 21), new User("u2", 21));
    System.out.println(userStream.distinct().count());
    System.out.println();

}

    public static List<User> initList() {
        List<User> list = new ArrayList<>();
        list.add(new User("oaby", 23));
        list.add(new User("tom", 11));
        list.add(new User("john", 16));
        list.add(new User("jennis", 26));
        list.add(new User("tin", 26));
        list.add(new User("army", 26));
        list.add(new User("mack", 19));
        list.add(new User("jobs", 65));
        list.add(new User("jordan", 23));
        return list;
   } 
}                                                                                                    

输出结果:

过滤-找出年纪大于18岁的人
User [username=oaby, age=23]
User [username=jennis, age=26]
User [username=tin, age=26]
User [username=army, age=26]
User [username=mack, age=19]
User [username=jobs, age=65]
User [username=jordan, age=23]
最大值-找出最大年纪的人
User [username=jobs, age=65]
映射-规纳-求所有人的年纪总和
235
分组-按年纪分组
{
16 = [User [username=john, age=16]]
65 = [User [username=jobs, age=65]]
19 = [User [username=mack, age=19]]
23 = [User [username=oaby, age=23], User [username=jordan, age=23]]
26 = [User [username=jennis, age=26], User [username=tin, age=26], User [username=army, age=26]]
11 = [User [username=tom, age=11]]
}
创建-去重-统计
2

但需要注意的是流只能执行一次,再次使用需要重要打开。


collection.stream()以及collect()方法


stream()方法和collect()方法都是java8的新特性

stream()优点

1.无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
2.为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
3.惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
4.可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。

stream().map()方法的使用示例:

List<String> list= Arrays.asList("a", "b", "c", "d");
List<String> collect =list.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect); //[A, B, C, D]

List<Integer> num = Arrays.asList(1,2,3,4,5);
List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(collect1); //[2, 4, 6, 8, 10]

Sprint Boot之注解@Qualifier、@Primary


1、@Qualifier

出现场景:

项目中有多个实现类实现同一个接口时,或者一个项目中有多个数据源时,spring容器不知道该注入哪个实现类或者使用哪个数据源,该注解就派上用场。如果不指定具体是哪个实现类的Bean,在Spring Boot启动时就会发生异常(下图):

请输入图片描述

异常的描述信息非常简单,就是告诉开发者,自动注入的地方需要一个Bean,而spring 容器却找到了3个实现类的Bean。

此时可以考虑使用@Primary注解或@Qualifier注解。
我们自动注入的时候,如果有多个候选实现类的bean,spring boot启动的时候就不知道该选择哪个bean进行注入,因此会报错。

使用@Primary可以指定一个首选Bean注入;使用@Qualifier可以在自动注入的地方通过传入一个限定名(也就是类的别名)来选取指定的实现类,只不过必须与类的别名一致(如果不传限定名,就使用类的默认别名)

如果既不用@Primary也不用@Qualifier,那就必须在自动注入的时候直接以类的默认别名来命名。

给(spring ioc容器管理的)类设置别名的方式是:@Service("别名")、@Component("别名") 、@Bean("别名") 等等。
例:

@Autowired
@Qualifier("apClearTaskFileService")
private IAPClearTaskFileService apClearTaskFileService;

@Service("apClearTaskFileService")
public class APClearTaskFileService extends BaseServiceImpl<TaskFileQO,TaskFileVO> implements IAPClearTaskFileService 

一辈子很短,努力的做好两件事就好;第一件事是热爱生活,好好的去爱身边的人;第二件事是努力学习,在工作中取得不一样的成绩,实现自己的价值,而不是仅仅为了赚钱


POI读取带有公式的Excel单元格


项目中需要使用Excel导入数据,读取Excel单元格的方法如下:

public static String getCellValue(Cell cell) {
    return getCellValue(cell, "dd/MM/yyyy");
}
public static String getCellValue(Cell cell, String pattern) {
    if (cell == null) {
        return "";
    }

    int cellType = cell.getCellType();

    if (cellType == Cell.CELL_TYPE_BLANK) {
        return "";
    }
    else if (cellType == Cell.CELL_TYPE_STRING) {
        String cellValue = cell.getStringCellValue().trim();
        return cellValue;
    }
    else if (cellType == Cell.CELL_TYPE_BOOLEAN) {
        return String.valueOf(cell.getBooleanCellValue());
    }
    else if (cellType == Cell.CELL_TYPE_NUMERIC) {
        if (HSSFDateUtil.isCellDateFormatted(cell)) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
            Date date = cell.getDateCellValue();

            return simpleDateFormat.format(date).toString();
        }
        else {
            DecimalFormat decimalFormat = new DecimalFormat("#.##");

            return decimalFormat.format(cell.getNumericCellValue());
        }
    }
            //此处为读取带有公式的单元格
    else if (cellType == Cell.CELL_TYPE_FORMULA) {
        try {
            return String.valueOf(cell.getStringCellValue());
        } catch (IllegalStateException e) {
            return BigDecimal.valueOf(cell.getNumericCellValue()).toString();
        }
    }

    return "";
}

这样对于字符串cell.getStringCellValue()方法即可取得其值,如果公式生成的是数值,使用cell.getStringCellValue()方法会抛出IllegalStateException异常,在异常处理中使用cell.getNumericCellValue();即可。

至于为何在发生异常时不直接return String.valueOf(cell.getNumericCellValue());是因为当使用POI处理excel的时候,遇到了比较长的数字,虽然excel里面设置该单元格是文本类型的,但是POI的cell的类型就会变成数字类型。 

而且无论数字是否小数,使用cell.getNumbericCellValue() 去获取值的时候,会得到一个double,而且当长度大一点的时候会变成科学计数法形式。 

那么获取这个单元格的原始的数据,就其实是一个double怎么转换成整数的问题了。


小驴奔腾实验室网站搭建记录


1.准备工作

  • 域名 : liferay.org.cn (100/year)
  • 空间 : 阿里云 (600/year)
  • 网站架构: LEMP = linux + Nginx{tomcat/Apache/JBOSS} + mysql + PHP
  • 网站程序: typecho {WordPress}
  • 位置/usr/local/www/liferay_org_cn

2.开始搭建网站

备案

填写备案信息,提交备案信息.

搭建LEMP

1.安装 Nginx 让我们从它的官方的 RPM 源来安装一个预构建的稳定版本的 nginx 包。
  • 在 CentOS 7 系统上:
- $ sudo rpm --import http://nginx.org/keys/nginx_signing.key
- $ sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
- $ sudo yum install nginx
2.启动 Nginx

安装完成后,nginx 是不会自动启动的。现在让我们来启动它吧,还要做些配置让其可以随着操作系统启动而启动。我们也需要在防火墙里打开 TCP/80 端口,以使得可以远程访问 nginx 的 web 服务。所有这些操作、设置都只需要输入如下命令就可实现。

  • 在 CentOS 7 系统上:
$  systemctl start nginx
$  systemctl enable nginx
$  firewall-cmd --zone=public --add-port=80/tcp--permanent
$  firewall-cmd --reload

3.测试 Nginx

nginx 的默认文档要目录是 /usr/share/nginx/html。默认的 index.html 文件一定已经在这目录下了。让我们检测下是否可以访问到这个测试 web 页,输入 http://nginx的ip地址/ 访问。

MariaDB/MySQL

centos7下使用yum安装mysql

CentOS7的yum源中默认好像是没有mysql的。为了解决这个问题,我们要先下载mysql的repo源。

  1. 下载mysql的repo源
$ wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
  1. 安装mysql-community-release-el7-5.noarch.rpm包
$ sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm

安装这个包后,会获得两个mysql的yum repo源:/etc/yum.repos.d/mysql-community.repo,/etc/yum.repos.d/mysql-community-source.repo。

  1. 安装mysql
$ sudo yum install mysql-server
  1. 重置密码

重置密码前,首先要登录

$ mysql -u root

登录时有可能报这样的错:ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock‘ (2),原因是/var/lib/mysql的访问权限问题。下面的命令把/var/lib/mysql的拥有者改为当前用户:

$ sudo chown -R openscanner:openscanner /var/lib/mysql

然后,重启服务:

$ service mysqld restart

接下来登录重置密码:

$ mysql -u root
mysql > use mysql;
mysql > update user set password=password(‘123456‘) where user=‘root‘;
mysql > exit;
  1. 开放3306端口
mysql> use mysql; 
mysql> update user set host = '%' where user = 'root'; 
mysql> select host, user from user; 
mysql> flush privileges;


$ sudo vim /etc/sysconfig/iptables

添加以下内容:

-A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT

保存后重启防火墙:

$ sudo service iptables restart

PHP

PHP 是 LEMP 包中一个重要的组件,它负责把存储在 MariaDB/MySQL 服务器的数据取出生成动态内容。为了 LEMP 需要,您至少需要安装上 PHP-FPM 和 PHP-MySQL 两个模块。PHP-FPM(FastCGI 进程管理器)实现的是 nginx 服务器和生成动态内容的 PHP 应用程序的访问接口。PHP-MySQL 模块使 PHP 程序能访问 MariaDB/MySQL 数据库。

安装 PHP 模块

  • CentOS 7 系统上:
$ sudo yum install php php-fpm php-mysql
  • CentOS 6 系统上:
$ sudo yum --enablerepo=remi install php php-fpm php-mysql

在安装 PHP 时,得注意两个地方:

在 CentOS 6 系统中,安装 REMI仓库中最新的 php-mysql 模块时,MySQL 的服务端包和客户端包会被当做一部分依赖包而自动的更新。

在 CentOS 6 和 CentOS 7 中,在安装 PHP 包的同时会把 Apache web 服务器(即 httpd)当做它的依赖包一起安装。这会跟 nginx web 服务器起冲突。这个问题会在下一节来讨论。

取决于您的使用情况,可以使用 yum 命令来定制您的 PHP 引擎,也许会想安装下面的任意一个扩展 PHP 模块包。

php-cli: PHP 的命令行界面。从命令行里测试 PHP 时非常有用。
php-gd: PHP 的图像处理支持。
php-bcmath: PHP 的数学支持。
php-mcrypt: PHP 的加密算法支持 (例如 DES、Blowfish、CBC、 CFB、ECB ciphers 等)。
php-xml: PHP 的 XML 解析和处理支持。
php-dba: PHP 的数据抽象层支持。
php-pecl-apc: PHP 加速器/缓存支持。

安装时,要查看可用的 PHP 模块的完整列表的话,可以运行:

$ sudo yum search php-(CentOS7)
$ sudo yum --enablerepo=remi search php-(CentOS6)

启动 PHP-FPM

您需要启动 PHP-FPM ,然后把它放到自动启动服务列表。

  • 在 CentOS 7 系统上:
$ sudo systemctl start php-fpm
$ sudo systemctl enable php-fpm
  • 在 CentOS 6 系统上:
$ sudo chkconfig php-fpm on
$ sudo service php-fpm start

第四步: 配置 LEMP 组合包

使 Httpd 不可用 首先,让我们把早先随 PHP 包安装的 httpd 服务给禁用掉。

  • 在 CentOS 7 系统上:
$ sudo systemctl disable httpd

配置 Nginx

接下来,让我们配置 nginx 虚拟主机,使得 nginx 可以通过 PHP-FPM 来处理 PHP 的任务。用文本编辑器打开 /etc/nginx/conf.d/default.conf ,然后按如下所示修改。

$ sudo vi /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name www.server_domain.com;
root /usr/share/nginx/html;
index index.php index.html index.htm;
 
location /{
}
 
# redirect server error pages to the static page /50x.html
error_page 500502503504/50x.html;
location =/50x.html {
}
 
# nginx passes PHP scripts to FastCGI server via a TCP/9000 socket
# this setting much be consistent with /etc/php-fpm.d/www.conf
# try_files prevents nginx from passing bad scripts to FastCGI server
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

注意 fastcgi_param 的$document_root部分.

nginx 的默认工作线程数(在 /etc/nginx/nginx.conf 文件中指定的)是 1,让我们也来调整一下这个数字。通常来说我们创建的工作线程数应该和 CPU 核数相同。要确信您的 CPU 的核数,请运行下面这命令:

$ grep processor /proc/cpuinfo | wc -l

如果您的 CPU 是 4 核的,就如下所示修改 /etc/nginx/nginx.conf 文件。

$ sudo vi /etc/nginx/nginx.conf

worker_processes 4;

配置 PHP

接下来,让我们对 PHP 的配置文件 /etc/php.ini 做自定义设置。更具体的就是在 /etc/php.ini 文件中增加以下两行。

cgi.fix_pathinfo=0
date.timezone ="PRC"

为了安全起见,我们希望的是 PHP 解释器只是处理指定文件路径的文件任务,而不是预测搜索一些并不存在的文件任务。上面的第一行起的就是这个作用。(LCTT 译注:原文用的时区是“America/New York”,根据国内情况,应该用 PRC或 Asia 下的中国城市。)

第二行定义的是 PHP 中日期/时间相关函数使用相关的默认时区。使用本指南,找出您所在的时区,并设置相应 date.timezone 的值。

测试 PHP

最后,让我们来测试下 nginx 是否能处理 PHP 页面。在测试之前,请确保重启 nginx 和 PHP-FPM。

  • 在 CentOS 7 系统上:
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

创建一个叫名叫 test.php 的文件,然后写入如下内容,并放入 /var/www/html/ 目录。

<?php phpinfo();?>

打开浏览器,输入 http://nginx的IP地址/test.php

域名解析

liferay.org.cn 解析到 阿里云地址 

PS : Typecho 在阿里云服务器, 部署成功之后, 点击文章标题网站并不跳转, 这时候需要在后台设置永久连接, 开启是否使用地址重写功能就可以.

Enjoy It, Guys!