密云区免费网站建设,app开发定制公司推荐,网站到期忘记续费,山东省住房和城乡建设部网站文章目录 一、命名规约二、集合篇1. 栈、队列、双端队列2. List的升序倒序3. Map的升序降序4. 二维数组排序5. 集合之间的转换6. Map键值对遍历 三、并发篇1. 创建线程池2. ThreadLocal的使用 四、时间篇1. LocalDateTime的使用2. String、Date、LocalDateTime转换 五、控制块1… 文章目录 一、命名规约二、集合篇1. 栈、队列、双端队列2. List的升序倒序3. Map的升序降序4. 二维数组排序5. 集合之间的转换6. Map键值对遍历 三、并发篇1. 创建线程池2. ThreadLocal的使用 四、时间篇1. LocalDateTime的使用2. String、Date、LocalDateTime转换 五、控制块1. switch2. 三目运算3. 循环体4. try-catch-finally-return 六、其他1. 正则表达式2. BeanUtil的copy 一、命名规约
A) 各类命名方法
类名UserController、UserService、UserMapper
模型名User、UserDTO、UserVO
对象名userController
常量名USER_NAMEB) Service/DAO 层方法命名规约
1 获取单个对象的方法用 get 做前缀。
2 获取多个对象的方法用 list 做前缀复数结尾如listObjects。
3 获取统计值的方法用 count 做前缀。
4 插入的方法用 save/insert 做前缀。
5 删除的方法用 remove/delete 做前缀。
6 修改的方法用 update 做前缀。注意POJO 类中布尔类型的变量都不要加 is 前缀否则部分框架解析会引起序列化错误。二、集合篇
1. 栈、队列、双端队列 StackInteger stack new Stack(); // 栈stack.push(1); // 压入stack.pop(); // 弹出stack.peek(); // 获取但不弹出QueueInteger queue new ArrayDeque(); //队列queue.offer(1); //压入queue.poll(); // 弹出queue.peek(); // 获取但不弹出DequeInteger deque new ArrayDeque(); // 双端队列deque.offerFirst(1); // 压入队头deque.offerLast(2); // 压入对尾deque.pollFirst(); // 弹出队头deque.pollLast(); // 弹出队尾deque.peekFirst(); // 获取队头但不弹出deque.peekLast(); // 获取队尾但不弹出2. List的升序倒序 ListInteger list Arrays.asList(10,1,6,4,8,7,9,3,2,5);System.out.println(原始数据);list.forEach(n -{System.out.print(n, );});System.out.println();System.out.println(升序排列);Collections.sort(list); // 升序排列list.forEach(n -{System.out.print(n, );});// 降序的话需要先升序再倒序才能有降序的结果System.out.println();System.out.println(降序排列);Collections.reverse(list); // 倒序排列list.forEach(n -{System.out.print(n, );});3. Map的升序降序 MapInteger, String map new HashMap();map.put(100, Iam a);map.put(99, Iam c);map.put(2, Iam d);map.put(33, Iam b);// 按照value进行倒排如果要根据key进行排序的话使用Map.Entry.comparingByKey()map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).forEach(System.out::println);// 根据value进行正序排序根据key进行排序的话使用comparingByKey()map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);// 如果要将排序的结果返回的话我们可以使用下面的方法注意要使用LinkedHashMap进行保存linkedHashMap可以保存插入顺序MapInteger, String resultMap1 map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (s, s2) - s,LinkedHashMap::new));// 下面的这种写法同上面的写法只不过是将简写展开了这样更易于理解MapInteger, String resultMap map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(new FunctionMap.EntryInteger, String, Integer() {Overridepublic Integer apply(Map.EntryInteger, String integerStringEntry) {return integerStringEntry.getKey();}}, new FunctionMap.EntryInteger, String, String() {Overridepublic String apply(Map.EntryInteger, String integerStringEntry) {return integerStringEntry.getValue();}}, new BinaryOperatorString() {Overridepublic String apply(String s, String s2) {return s;}}, new SupplierMapInteger, String() {Overridepublic MapInteger, String get() {return new LinkedHashMap();}}));// 同样如果需要将排序的将结果作为Map进行返回我们还可以使用下面的方法但是不推荐这种方式effectivejava 178页中说foreach操作应该只用于报告stream计算的结果而不是执行计算MapInteger, String result2 new LinkedHashMap();map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(new ConsumerMap.EntryInteger, String() {Overridepublic void accept(Map.EntryInteger, String integerStringEntry) {result2.put(integerStringEntry.getKey(), integerStringEntry.getValue());}});4. 二维数组排序
Arrays.sort(intervals, new Comparatorint[]() {public int compare(int[] interval1, int[] interval2) {return interval1[0] - interval2[0];}});5. 集合之间的转换
// Object转基本元素
ListString tableNameslist.stream().map(User::getMessage).collect(Collectors.toList());// Object转Map
MapString, Account map accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) - key2));// Object转Map
/** * 1. 避免key重复* 在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时一定要使* 用含有参数类型为 BinaryOperator参数名为 mergeFunction 的方法否则当出现相同 key* 值时会抛出 IllegalStateException 异常。* 说明参数 mergeFunction 的作用是当出现 key 重复时自定义对 value 的处理策略* 2. 避免值为null* 在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时一定要注* 意当 value 为 null 时会抛 NPE 异常。
**/
MapLong, String getIdNameMap accounts.stream().collect(Collectors.toMap(Account::getId, Account::getUsernamee, (v1, v2) - v2));// String转Long
ListLongstringList.stream().map(Long::valueOf).collect(Collectors.toList());// Long转String
ListStringlongList.stream().map(String::valueOf).collect(Collectors.toList());// Integer转Long
ListLong listLong JSONArray.parseArray(listInt.toString(),Long.class);// Long 转Integer
ListInteger integerList JSONArray.parseArray(LongList.toString(), Integer.class);
// 或者
ListInteger integerList longList.stream().map(x - Integer.valueOf(String.valueOf(x))).collect(Collectors.toList());// JSONArray转List
JSONArray jsonArray updateApplicationSchemaDTO.getJSONArray(configTrophyDTOList);
configTrophyDTOList jsonArray.toJavaList(ConfigTrophyDTO.class);// List转数组
String[] array list.toArray(new String[0]);// 数组转List
List list Arrays.asList(strArray);6. Map键值对遍历
System.out.println(4、通过entrySet()获得key-value值——使用迭代器遍历);
Set set1 hashMap.entrySet();
Iterator iterator1 set1.iterator();
while(iterator1.hasNext()){Object itset iterator1.next();Map.Entry entry (Map.Entry) itset;System.out.println(entry.getKey()-entry.getValue());
}三、并发篇
1. 创建线程池
ThreadPoolExecutor 参数介绍 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {}参数 1corePoolSize 核心线程数线程池中始终存活的线程数。
参数 2maximumPoolSize 最大线程数线程池中允许的最大线程数当线程池的任务队列满了之后可以创建的最大线程数。
参数 3keepAliveTime 最大线程数可以存活的时间当线程中没有任务执行时最大线程就会销毁一部分最终保持核心线程数量的线程。
参数 4unit: 单位是和参数 3 存活时间配合使用的合在一起用于设定线程的存活时间 参数 keepAliveTime 的时间单位有以下 7 种可选
TimeUnit.DAYS天
TimeUnit.HOURS小时
TimeUnit.MINUTES分
TimeUnit.SECONDS秒
TimeUnit.MILLISECONDS毫秒
TimeUnit.MICROSECONDS微妙
TimeUnit.NANOSECONDS纳秒参数 5workQueue 一个阻塞队列用来存储线程池等待执行的任务均为线程安全它包含以下 7 种类型较常用的是 LinkedBlockingQueue 和 Synchronous线程池的排队策略与 BlockingQueue 有关。
ArrayBlockingQueue一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue一个由链表结构组成的有界阻塞队列。
SynchronousQueue一个不存储元素的阻塞队列即直接提交给线程不保持它们。
PriorityBlockingQueue一个支持优先级排序的无界阻塞队列。
DelayQueue一个使用优先级队列实现的无界阻塞队列只有在延迟期满时才能从中提取元素。
LinkedTransferQueue一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似还含有非阻塞方法。
LinkedBlockingDeque一个由链表结构组成的双向阻塞队列。参数 6threadFactory 线程工厂主要用来创建线程默认为正常优先级、非守护线程。
参数 7handler 拒绝策略拒绝处理任务时的策略系统提供了 4 种可选默认策略为 AbortPolicy。
AbortPolicy拒绝并抛出异常。
CallerRunsPolicy使用当前调用的线程来执行此任务。
DiscardOldestPolicy抛弃队列头部最旧的一个任务并执行当前任务。
DiscardPolicy忽略并抛弃当前任务。ThreadPoolExecutor执行流程 ThreadPoolExecutor 关键节点的执行流程如下
当线程数小于核心线程数时创建线程。当线程数大于等于核心线程数且任务队列未满时将任务放入任务队列。当线程数大于等于核心线程数且任务队列已满若线程数小于最大线程数创建线程若线程数等于最大线程数抛出异常拒绝任务。
ThreadPoolExecutor自定义拒绝策略
public static void main(String[] args) {// 任务的具体方法Runnable runnable new Runnable() {Overridepublic void run() {System.out.println(当前任务被执行,执行时间: new Date() 执行线程: Thread.currentThread().getName());try {// 等待 1sTimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}};// 创建线程,线程的任务队列的长度为 1ThreadPoolExecutor threadPool new ThreadPoolExecutor(1, 1,100, TimeUnit.SECONDS, new LinkedBlockingQueue(1),new RejectedExecutionHandler() {Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {// 执行自定义拒绝策略的相关操作System.out.println(我是自定义拒绝策略~);}});// 添加并执行 4 个任务threadPool.execute(runnable);threadPool.execute(runnable);threadPool.execute(runnable);threadPool.execute(runnable);
}2. ThreadLocal的使用
/**
ThreadLocal的api很简单就4个* get——获取threadlocal局部变量* set——设置threadlocal局部变量* initialvalue——设置局部变量的初始值* remove——删除该局部变量
**/
public class SequenceNumber { // ThreadLocal 对象使用 static 修饰ThreadLocal 无法解决共享对象的更新问题。private static ThreadLocalInteger seqNum new ThreadLocalInteger(){ public Integer initialValue(){ return 0; } }; public int getNextNum() { seqNum.set(seqNum.get() 1); return seqNum.get(); } public static void main(String[] args) { SequenceNumber sn new SequenceNumber(); TestClient t1 new TestClient(sn); TestClient t2 new TestClient(sn); TestClient t3 new TestClient(sn); t1.start(); t2.start(); t3.start(); t1.print(); t2.print(); t3.print(); }
}private static class TestClient extends Thread { private SequenceNumber sn; public TestClient(SequenceNumber sn ) { this.sn sn; } public void run() { for(int i0; i 3; i) { System.out.println( Thread.currentThread().getName() -- sn.getNextNum()); } } public void print() { for(int i0; i 3; i) { System.out.println( Thread.currentThread().getName() -- sn.getNextNum()); } }
} Thread-2 -- 1
Thread-2 -- 2
Thread-2 -- 3
Thread-0 -- 1
Thread-0 -- 2
Thread-0 -- 3
Thread-1 -- 1
Thread-1 -- 2
Thread-1 -- 3
main -- 1
main -- 2
main -- 3
main -- 4
main -- 5
main -- 6
main -- 7
main -- 8
main -- 9 结论可以发现static的ThreadLocal变量是一个与线程相关的静态变量即一个线程内static变量是被各个实例共同引用的但是不同线程内static变量是隔开的。
四、时间篇
1. LocalDateTime的使用
// 获取当前时间
LocalDateTime now LocalDateTime.now();// 获取指定时间
LocalDateTime localDateTime LocalDateTime.of(2021, 6, 16, 16, 37, 20, 814 * 1000 * 1000);
LocalDateTime ldt LocalDateTime.now().withYear(2021).withMonth(6).withDayOfMonth(16).withHour(10).withMinute(10).withSecond(59).withNano(999 * 1000 * 1000);// 获取指定时区时间
LocalDateTime datetime LocalDateTime.now(ZoneId.of(Asia/Shanghai));
LocalDateTime datetime2 LocalDateTime.now(ZoneId.of(8));// 获取年月日信息
LocalDateTime now LocalDateTime.now();
int year now.getYear();
int month now.getMonthValue();
int dayOfYear now.getDayOfYear();
int dayOfMonth now.getDayOfMonth();
int hour now.getHour();
int minute now.getMinute();
int second now.getSecond();
int nano now.getNano();// 日期计算
LocalDateTime now LocalDateTime.now();
LocalDateTime tomorrow now.plusDays(1L);
tomorrow tomorrow.plusHours(2L);
tomorrow tomorrow.plusMinutes(10L);LocalDateTime yesterday now.minus(Duration.ofDays(1));
yesterday yesterday.plusHours(2L);
yesterday yesterday.plusMinutes(10L);// 时间格式化DateTimeFormatter是线程安全的类。
DateTimeFormatter df DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);
String format LocalDateTime.now().format(df);2. String、Date、LocalDateTime转换
// LocalDateTime转Date
public static Date localDateTime2Date(LocalDateTime localDateTime) {return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}// LocalDateTime转String
private static final DateTimeFormatter DATE_TIME_FORMATTER DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);
public static String localDateTime2String(LocalDateTime localDateTime) {return localDateTime.format(DATE_TIME_FORMATTER);
}// String 转 LocalDateTimeDateTimeFormatter是线程安全的类可以将此类放到常量中。
private static final DateTimeFormatter DATE_TIME_FORMATTER DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);
public static LocalDateTime string2LocalDateTime(String str) {return LocalDateTime.parse(str, DATE_TIME_FORMATTER);
}// String 转 DateSimpleDateFormat是非线程安全的类在多线程操作时会报错。
public static Date string2Date(String str) throws ParseException {SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return simpleDateFormat.parse(str);
}// Date 转 LocalDateTime
public static LocalDateTime date2LocalDateTime(Date date) {return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}// Date 转 String
public static String date2String(Date date) {SimpleDateFormat formatter new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return formatter.format(date);
}五、控制块
1. switch
public class SwitchString {public static void main(String[] args) {method(sth);}public static void method(String param) {// 1. 当 switch 括号内的变量类型为 String 并且为外部参数时必须先进行 null判断。if(StringUtils.isEmpty(param)){return;}switch(param){casesth: System.out.printin(its sth); break;casesb: System.out.println(its sb); break;// 2. 在一个 switch 块内都必须包含一个 default语句并且放在最后default: System.out.println(default); break;}}
}2. 三目运算
三目运算符 condition? 表达式 1 : 表达式 2 中高度注意表达式 1 和 2 在类型对齐 时可能抛出因自动拆箱导致的 NPE 异常。
// 反例
Integer a 1;
Integer b 2;
Integer c null;
Boolean flag false;
// a*b 的结果是 int 类型那么 c 会强制拆箱成 int 类型抛出 NPE 异常
Integer result(flag? a*b : c);3. 循环体
1. 循环体中的语句要考量性能以下操作尽量移至循环体外处理如定义对象、变量、 获取数据库连接进行不必要的 try-catch 操作这个 try-catch 是否可以移至循环体外
4. try-catch-finally-return
return的执行优先级高于finally的执行优先级但是return语句执行完毕之后并不会马上结束函数而是将结果保存到栈帧中的局部变量表中然后继续执行finally块中的语句如果finally块中包含return语句则不会对try块中要返回的值进行保护而是直接跳到finally语句中执行并最后在finally语句中返回返回值是在finally块中改变之后的值
// return 1
public static int test1() {int x 1;try {return x;} finally {x 2;}
}// return 2
public static int test2() {int x 1;try {return x;} finally {x 2;return x;}
}六、其他
1. 正则表达式
在使用正则表达式时利用好其预编译功能可以有效加快正则匹配速度。
// 反例
public void addSyncConfigToCache(String configName, ESSyncConfig config) {Pattern pattern Pattern.compile(.*:(.*)://.*/(.*)\\?.*$);Matcher matcher pattern.matcher(dataSource.getUrl());
}// 正例
private static final Pattern pattern Pattern.compile(regexRule);
public void addSyncConfigToCache(String configName, ESSyncConfig config) {Matcher matcher pattern.matcher(dataSource.getUrl());
}2. BeanUtil的copy
Apache BeanUtils 性能较差可以使用其他方案比如 Spring BeanUtils, Cglib BeanCopier注意 均是浅拷贝。
Person source Person(Alice, 25);
Person destination new Person();
BeanUtils.copyProperties(destination, source);