stream流的应用与并行流与函数式编程

 直接使用stream流

public class Stream {public static void main(String[] args) {
    //ArrayList<Object> arrayList = new ArrayList<>(); //List集合不安全,stream().parallel()操作不行

    List<Object> arrayList = Collections.synchronizedList(new ArrayList<>());//解决方法一:集合工具类
 // CopyOnWriteArrayList<Object> arrayList = new CopyOnWriteArrayList<>(); //解决方法二:JUC的集合
    for (int i = 1; i <= 100000; i++) {
        arrayList.add(String.valueOf(i));
    }
    System.out.println("-------------------使用串行流--------------------");
    ArrayList<Object> result1 = new ArrayList<>();
    long start = System.currentTimeMillis();
    arrayList.forEach((str)->{
//        System.out.println(Thread.currentThread().getName()+",操作中。。。");
        result1.add(new User(2, (String) str,22));
    });
  //  System.out.println("使用串行流,修改集合"+result1);
    System.out.println("花费的时间为:"+(System.currentTimeMillis()-start));

    System.out.println("-------------------使用并行流--------------------");
    //这里使用的集合需要注意,不能使用常规的集合,在扩容的时候会出现数组下标越界异常,经过测试CopyOnWriteArrayList集合效率比较低下,因为CopyOnWriteArrayList,在写操作的时候会新建集合
    List<Object> result2 = Collections.synchronizedList(new ArrayList<>());
  //CopyOnWriteArrayList<Object> arrayList = new CopyOnWriteArrayList<>();
    start = System.currentTimeMillis();
    arrayList.stream().parallel().forEach((str)->{
        //System.out.println(Thread.currentThread().getName()+",操作中。。。");
        result2.add(new User(2, (String) str,22));
    });
 //   System.out.println("使用并行流,修改集合"+result2);
    System.out.println("花费的时间为:"+(System.currentTimeMillis()-start));
}

}

add操作使用的集合需要注意,不能使用常规的集合,在扩容的时候会出现数组下标越界异常,经过测试CopyOnWriteArrayList集合效率比较低下,因为CopyOnWriteArrayList,在写操作的时候会新建集合,JUC包下的一些集合是可以用的,或者是加锁的集合,但是效率不一定会很高,数据量太大也会导致内存泄漏OOM问题

 使用IntStream流

 @Test
    public void testStream(){
        IntStream intStream = IntStream.of(6, 1, 1, 2, 5, 2, 3, 4);
        long start=System.currentTimeMillis();
        //并行处理
        intStream.parallel().forEach(x->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+x);
        });
        System.out.println("parallel time->"+(System.currentTimeMillis()-start));

        intStream = IntStream.of(6, 1, 1, 2, 5, 2, 3, 4);
        start=System.currentTimeMillis();
        //默认都是串行处理
        intStream.sequential().forEach(x->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+x);
        });
        System.out.println("sequential time->"+(System.currentTimeMillis()-start));
    }

 在使用并行流的时候一定要注意线程安全问题,而且并不能保证多个线程之间顺序执行,多线程还需要考虑原子性可见性指令重排等问题,而且效率也不一定会比串行流高很多,在使用的时候需要慎重考虑优劣,毕竟带来的问题还是比较多的

查询表中是否存在想要的记录:

select 1 from table where  。。。 limit 1

在queryMapper后拼接limit条件:

String 中就是sql语句例如:"limit 1"

querymapper.last(String)

遇到很多个表结构差不多的情况,使用反射加上泛型就可以封装一个通用的mapper,这个就是随便写的一个Demo,不一定对,随便瞎写的,大概就是这个意思

public <T,R> R baseMapper(R request,Class<T> po){

QueryMapper<T> queryMapper=new QueryMapper();
//这里使用反射获取request的属性,然后拼接mapper条件,其实就相当于写死了,然后判断属性值是否为null,来拼接sql
queryMapper.eq("name",request.hetClass().getgetDeclaredField("name").get(request));
//这里如果属性是私有的话,可以setAccessible(true),来破坏私有属性
return queryMapper;

}

idea当前类全局替换: ctrl+r  ,还可以排除不想替换的词

idea大小写转换快捷键:ctrl+shift+u

idea全局替换:ctrl+shift+r

获取ip地址,这个在多节点情况下对于排查问题时是很有必要的:

InetAddress.getLocalHost().getHostAddress()

 stream流将两个集合合并成一个map,一个集合的值当key,一个集合的值为value;这里需要注意key的唯一性问题

public static void main(String[] args) {

        List<Integer> keyList = new ArrayList<>();
        List<String> valueList = new ArrayList<>();
        keyList.add(1);
        keyList.add(2);
        keyList.add(3);
        keyList.add(4);
        keyList.add(5);
        valueList.add("张三");
        valueList.add("李四");
        valueList.add("王五");
        valueList.add("赵六");
        valueList.add("钱七");
        //使用stream流的方式,把这两个list集合长度一样合并成一个map集合
        //将list转换map
        Map<Object, Object> map = keyList.stream().collect(Collectors.toMap(key -> key, value -> valueList.get(keyList.indexOf(value))));
        System.out.println(map);
        //最终需要的结果 {1=张三, 2=李四, 3=王五, 4=赵六, 5=钱七}
    }

 从一个集合中截取指定区间的数据:

ArrayList.subList() ; (左开右闭)

boolean类型的参数尽量不要用is来命名,因为某些框架会自动将Boolean类型参数的is去掉

 private Boolean isShow;  ->  private boolean show;

 将两个集合合并成一个集合

        List<String> list1 = Arrays.asList("阿卫", "阿辉", "阿杰", "阿成");
        List<String> list2 = Arrays.asList("阿悦", "阿楠", "阿洁", "阿锋");
        Stream.concat(list1.stream(),list2.stream());

 时间类型作比较

before()和after()方法  必须格式一致

compareTo()方法 返回boolean类型

或者将时间转换为毫秒作比较  getTime()方法

stream流分组排序

   LinkedHashMap<Integer, List<Person>> ageMap = persons.stream().sorted(Comparator.comparingInt(Person::getAge)).collect(Collectors.groupingBy(Person::getAge, LinkedHashMap::new, Collectors.toList()));

 多字段排序

//先以userId降序,再进行userName升序 **推荐使用该种方式**
    list =  list.stream().sorted(Comparator.comparing(User::getUserId,Comparator.reverseOrder()).thenComparing(User::getUserName)).collect(Collectors.toList());
 

 数组进行翻转

Collections.reverse(arrayList)

 自定义常量集合

 /** 常量值列表 */
    public static final List<Integer> CONST_VALUE_LIST = Collections.unmodifiableList(Arrays.asList(1, 2, 3));
    /** 常量值集合 */
    public static final Set<Integer> CONST_VALUE_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(1, 2, 3)));
    /** 常量值映射 */
    public static final Map<Integer, String> CONST_VALUE_MAP;
    static {
        Map<Integer, String> valueMap = new HashMap<>();
        valueMap.put(1, "value1");
        valueMap.put(2, "value2");
        valueMap.put(3, "value3");
        CONST_VALUE_MAP = Collections.unmodifiableMap(valueMap);
    }

 分割字符串

String dirDiveded[] = fileName.split("/"); String newName = ""; if(dirDiveded.length > 0){ newName = dirDiveded[dirDiveded.length-1]; }

 String newName = fileName.substring(fileName.lastIndexOf("/")+1);

http下载

 public static void download(List urlStringList) {
        OutputStream os = null;
        InputStream is = null;
        try {
            for (Object urlStringObj : urlStringList) {
                String urlString = (String) urlStringObj;
                // 构造URL
                URL url = new URL(urlString);
                // 打开连接
                URLConnection con = url.openConnection();
                //设置请求超时为5s
                con.setConnectTimeout(5 * 1000);
                // 输入流
                is = con.getInputStream();
                // 1K的数据缓冲
                byte[] bs = new byte[1024];
                // 读取到的数据长度
                int len;
                // 路径
                String filename = urlString.substring(urlString.lastIndexOf("/"));
//                System.out.println(filename);
//                String str = urlString.split(filename)[0];
//                System.out.println(str);
//                String[] split = str.split("//");
//                int i = split[1].indexOf("/");
//                String substring = split[1].substring(i);
//                System.out.println(substring);
 
                // 输出的文件流
                File sf = new File(savePath);
                if (!sf.exists()) {
                    sf.mkdirs();
                }
                os = new FileOutputStream(sf.getPath() + filename+fileType);
                // 开始读取
                while ((len = is.read(bs)) != -1) {
                    os.write(bs, 0, len);
                }
//                System.out.println("下载完成");
            }
            // 完毕,关闭所有链接
            os.close();
            is.close();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(null != os){
                    os.close();
                }
                if(null != is){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
 
    }

异常处理:Cannot call sendError() after the response has been committed

 原因是在流关闭之后接口还返回了数据,使接口返回void即可解决

 Protocol handler start failed :端口占用

返回流设置类型:

response.setContentType("multipart/form-data");

 返回流,设置文件名称中文失效:

 response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));

 异常处理:getOutputStream() has already been called for this response

在getOutputStream()和getWriter()中间,使用respomse.reset()方法

 日志打印:

log.error("BasicFileFacade的update()方法不成功,参数为{}",updateFileRequest);

 BigDecimal科学计数法问题

科学计数法:toString()
不使用科学计数法:toPlainString()

Java8 Stream 流中的匹配查找方法

findAny:查找任何一个就返回 Optional
findFirst:查找到第一个就返回 Optional
anyMatch:匹配上任何一个则返回 Boolean
allMatch:匹配所有的元素则返回 Boolean

public enum SwitchEnum {

    ONE(1, "x"),
    TWO(2, "x"),
    THREE(3, "x2");

    private int type;
    private String name;

    SwitchEnum(int type, String name) {
        this.type = type;
        this.name = name;
    }

    // 查找某一个枚举值
    public static SwitchEnum findAny(int type) {
        return Arrays.stream(SwitchEnum.values())
                .filter(switchEnum -> switchEnum.getType() == type)
                .findAny()
                .orElse(null);
    }

    // 匹配到第一个枚举值就返回
    public static SwitchEnum findFirst(String name) {
        return Arrays.stream(SwitchEnum.values())
                .filter(switchEnum -> switchEnum.getName().equals(name))
                .findFirst()
                .orElse(null);
    }


    // 枚举匹配
    public static boolean anyMatch(int type) {
        return Arrays.stream(SwitchEnum.values())
                //匹配任何一个则返回
                .anyMatch(switchEnum -> switchEnum.getType() == type);
    }

    // 枚举匹配
    public static boolean allMatch(String name) {
        return Arrays.stream(SwitchEnum.values())
                //匹配所有
                .allMatch(switchEnum -> switchEnum.getName().equals(name));
    }


    public int getType() {
        return type;
    }


    public String getName() {
        return name;
    }

    public static void main(String[] args) {
        System.out.println("findAny============>" + findAny(1));
        System.out.println("findFirst============>" + findFirst("x"));
        System.out.println("anyMatch============>" + anyMatch(2));
        System.out.println("anyMatch============>" + allMatch("x"));
    }
}
 

 fifter使用:fifter留下的是过滤条件中为true的

public class StreamTest{
    public static void main(String[] args){
        List<User> list = new ArrayList<>();
        //定义三个用户对象
        User user1 = new User();
        user1.setUsername("huxiansen");
        user1.setPassword("123456");
        User user2 = new User();
        user2.setUsername("huxianseng");
        user2.setPassword("123456");
        User user3 = new User();
        user3.setUsername("huxiansen");
        user3.setPassword("12345");
        //添加用户到集合中
        list.add(user1);
        list.add(user2);
        list.add(user3);

        //在集合中查询用户名为huxiansen的集合
        List<User> userList = list.stream().filter(user -> "huxiansen".equals(user.getUsername())).collect(Collectors.toList());
        //在集合中查询出第一个用户密码为123456的用户
        Optional<User> user = list.stream().filter(userTemp -> "123456".equals(userTemp.getPassword())).findFirst();

        System.out.println(userList);
        System.out.println(user);
    }
}```
 

 stream去重:

distinct()

 list.stream().dintnct().map()   这样是对整体去重

 list.stream().map().dintinct()   这样是对map之后的结果去重

stream分组

Map <String,List <QueryPensionIncome>>collect1=queryPensionIncomeList.stream().collect(Collectors.groupingBy(QueryPensionIncome::getIncomeDate));

函数式编程 

其实写法就和stream流差不多,就是将方法作为参数传递进另一个方法,来执行一些逻辑

 

public interface TestInterface<T> {

    void execute(TestInterface2<T> message, Integer integer);

    void doSend(String message);
}

定义这个接口得实现

@Component
public class TestInterfaceImpl implements TestInterface{


    @Override
    public void execute(TestInterface2 message, Integer integer) {
        System.out.println(integer);
        if (message!=null){
            System.out.println("sss");
        }
        message.execute("sss",1);
    }


    @Override
    public void doSend(String message) {
        System.out.println("发送成功");
    }
}

 

然后定义一个接口用来调用,这个接口不用写实现 ,用抽象类也可以

@FunctionalInterface
public interface TestInterface2<T> {

    void execute(String message, Integer integer);
}

写一个测试类测试一下

@Test
public void testMain() {
    testInterface.execute((message, integer) -> {
        System.out.println("interface");
        testInterface.doSend("xxxx");
        System.out.println(integer);
        System.out.println(message);
    }, 1);
}

 

 

如有其他问题评论区见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值