直接使用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);
}
如有其他问题评论区见