首页
统计
留言板
直播
更多
壁纸
推荐
Git仓库
Search
1
IntelliJ IDEA激活 - 至2022年10月 (持续更新)
645 阅读
2
GitLab企业版搭建(附生成证书)
626 阅读
3
淘宝 京东秒杀脚本
422 阅读
4
Groovy模板引擎 API 构建动态脚本
324 阅读
5
欢迎使用 Typecho
294 阅读
杂货间
开发
Java
JavaScript
Android
JQuery
MySQL
PHP
Groovy
Git
运维
CentOS
Red Heat
Ubuntu
Debian
运行环境
登录
/
注册
Search
标签搜索
开发
Java
Android
MySQL8
CentOS
CentOS8
Linux
Git
Swing
JavaScript
JQuery
MySQL
临时手机号
IDEA
Steam
YouTube
订阅
激活码
GitLab
nginx
Dotdotmaples
累计撰写
30
篇文章
累计收到
7
条评论
首页
栏目
杂货间
开发
Java
JavaScript
Android
JQuery
MySQL
PHP
Groovy
Git
运维
CentOS
Red Heat
Ubuntu
Debian
运行环境
页面
统计
留言板
直播
壁纸
推荐
Git仓库
搜索到
9
篇与
Java
的结果
Java 工具类
将一个类中的值通过setter和getter传递给另一个类型public static <T> T entityToDto(Object entity, Class<T> dtoType) { T instance; try { instance = dtoType.getDeclaredConstructor().newInstance(); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); } // 反射entity 获取getter Class<?> entryType = entity.getClass(); Arrays.stream(dtoType.getMethods()).filter( method -> method.getName().startsWith("set") ).forEach(method -> { String methodName = method.getName().replace("set", "get"); try { Object value = entryType.getMethod(methodName).invoke(entity); method.invoke(instance, value); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignore) {} }); return instance; }
2022年05月12日
105 阅读
0 评论
1 点赞
计算Map初始容量算法
在实际开发中经常需要使用到Map,但给Map一个怎样的初始容量比较合理?众所周知是最接近(要大于)数据长度的2的N次方那么,如何计算?欢迎指出错误/** * 计算Map初始容量 * @author 枫铃也 * @since 2019-10-09 15:51 */ public class CapacityUtil { private static final double MODULE = 2; public static int getCapacityFactor(int size) { int n = size; int power = 0; while (n > 1) { power++; n >>>= 1; } int capacity = (int) Math.pow(MODULE, power); if (capacity < size || capacity % MODULE != 0) { capacity *= MODULE; } return capacity; } }欢迎指出错误
2019年10月11日
116 阅读
0 评论
1 点赞
2019-10-10
Java阿拉伯数字转中文数字
带单位转换的我只将数字范围定在十万以内的正数并且没考虑 0需要向上调整范围的童鞋自己修改代码呦欢迎指出错误先看效果再看代码不多说屁话上代码/** * <p>@description: 阿拉伯数字转中文数字(不带单位) </p> * <p>@method: numberConvertToBaseChinese </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-10 16:03 </p> * * <p>@return java.lang.String </p> */ public static String numberConvertToBaseChinese(int num) { StringBuffer buffer = new StringBuffer(); char[] nums = {'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'}; char[] baseChar = Integer.toString(num).toCharArray(); for (char c : baseChar) { buffer.append(nums[c - 48]); } return buffer.toString(); } /** * <p>@description: 阿拉伯数字转中文数字(带单位) </p> * <p>@method: numberConvertToChinese </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-10 16:03 </p> * * <p>@return java.lang.String </p> */ public static String numberConvertToChinese(int num) { char[] nums = {'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'}; char[] units = {' ', '十', '百', '千', '万'}; char[] baseChar = Integer.toString(num).toCharArray(); char[] numChar = new char[baseChar.length]; for (int i = 0; i < baseChar.length; i++) { numChar[i] = nums[baseChar[i] - 48]; } char[] unit = new char[numChar.length]; unit = Arrays.copyOf(units, unit.length); StringBuffer buffer = new StringBuffer(); for (int i = 0; i < numChar.length; i++) { if (numChar[i] != nums[0]) { buffer.append(numChar[i]).append(unit[unit.length - i - 1]); }else { buffer.append(numChar[i]); } } int index = 0; while ((index = buffer.indexOf(nums[0] + String.valueOf(nums[0]))) > 0) { buffer.replace(index, index + 2, String.valueOf(nums[0])); } return buffer.toString().substring(0, buffer.length() - 1); }神马,没有注释?我故意的(此处拒绝板砖和拖鞋之类的具有任何杀伤性的物品),嘿嘿自己看懂了才算是有收获欢迎指出错误
2019年10月10日
49 阅读
0 评论
0 点赞
日期工具类
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; /** * @author 枫铃也 * @since 2019-10-09 13:51 */ public class DateUtil { private static final TimeZone TIME_ZONE = TimeZone.getDefault(); private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static String format(Date date) { return DATE_FORMAT.format(date); } /** * <p>@description: 得到当前日历 </p> * <p>@method: getCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:47 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getCalendar() { return Calendar.getInstance(TIME_ZONE); } /** * <p>@description: 得到当前秒的开始日历 </p> * <p>@method: getSecondStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getSecondStartCalendar() { Calendar calendar = getCalendar(); //将毫秒至0 calendar.set(Calendar.MILLISECOND, 0); return calendar; } /** * <p>@description: 得到上一秒的开始日历 </p> * <p>@method: getLastSecondStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastSecondStartCalendar() { Calendar calendar = getSecondStartCalendar(); //将秒为上一秒 calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 1); return calendar; } /** * <p>@description: 得到下一秒的开始日历 </p> * <p>@method: getLaterSecondStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterSecondStartCalendar() { Calendar calendar = getSecondStartCalendar(); //将秒为下一秒 calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 1); return calendar; } /** * <p>@description: 得到当前秒的结束日历 </p> * <p>@method: getSecondEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getSecondEndCalendar() { Calendar calendar = getCalendar(); //将毫秒至999 calendar.set(Calendar.MILLISECOND, 999); return calendar; } /** * <p>@description: 得到上一秒的结束日历 </p> * <p>@method: getLastSecondEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastSecondEndCalendar() { Calendar calendar = getSecondEndCalendar(); //将秒置上一秒 calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 1); return calendar; } /** * <p>@description: 得到下一秒的结束日历 </p> * <p>@method: getLaterSecondEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterSecondEndCalendar() { Calendar calendar = getSecondEndCalendar(); //将秒置下一秒 calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 1); return calendar; } /** * <p>@description: 得到当前分钟的开始日历 </p> * <p>@method: getMinuteStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getMinuteStartCalendar() { Calendar calendar = getSecondStartCalendar(); //将秒至0 calendar.set(Calendar.SECOND, 0); return calendar; } /** * <p>@description: 得到上一分钟的开始日历 </p> * <p>@method: getLastMinuteStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastMinuteStartCalendar() { Calendar calendar = getMinuteStartCalendar(); //将分钟置上一分钟 calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 1); return calendar; } /** * <p>@description: 得到下一分钟的开始日历 </p> * <p>@method: getLaterMinuteStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterMinuteStartCalendar() { Calendar calendar = getMinuteStartCalendar(); //将分钟置下一分钟 calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 1); return calendar; } /** * <p>@description: 得到当前分钟的结束日历 </p> * <p>@method: getMinuteEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getMinuteEndCalendar() { Calendar calendar = getSecondEndCalendar(); //将秒至59 calendar.set(Calendar.SECOND, 59); return calendar; } /** * <p>@description: 得到上一分钟的结束日历 </p> * <p>@method: getLastMinuteEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastMinuteEndCalendar() { Calendar calendar = getMinuteEndCalendar(); //将分钟为上一分钟 calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 1); return calendar; } /** * <p>@description: 得到下一分钟的结束日历 </p> * <p>@method: getLaterMinuteEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterMinuteEndCalendar() { Calendar calendar = getMinuteEndCalendar(); //将分钟为下一分钟 calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 1); return calendar; } /** * <p>@description: 得到当前小时的开始日历 </p> * <p>@method: getHourStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getHourStartCalendar() { Calendar calendar = getMinuteStartCalendar(); //将分钟置0 calendar.set(Calendar.MINUTE, 0); return calendar; } /** * <p>@description: 得到上一小时的开始日历 </p> * <p>@method: getLastHourStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastHourStartCalendar() { Calendar calendar = getHourStartCalendar(); //将小时置上一小时 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1); return calendar; } /** * <p>@description: 得到下一小时的开始日历 </p> * <p>@method: getLaterHourStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterHourStartCalendar() { Calendar calendar = getHourStartCalendar(); //将小时置下一小时 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1); return calendar; } /** * <p>@description: 得到当前小时的结束日历 </p> * <p>@method: getHourEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getHourEndCalendar() { Calendar calendar = getMinuteEndCalendar(); //将分钟置59 calendar.set(Calendar.MINUTE, 59); return calendar; } /** * <p>@description: 得到上一小时的结束日历 </p> * <p>@method: getLastHourEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastHourEndCalendar() { Calendar calendar = getHourEndCalendar(); //将小时置上一小时 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1); return calendar; } /** * <p>@description: 得到下一小时的结束日历 </p> * <p>@method: getLaterHourEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterHourEndCalendar() { Calendar calendar = getHourEndCalendar(); //将小时置下一小时 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1); return calendar; } /** * <p>@description: 得到当前日的开始日历 </p> * <p>@method: getDayStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getDayStartCalendar() { Calendar calendar = getHourStartCalendar(); //将小时置0 calendar.set(Calendar.HOUR_OF_DAY, 0); return calendar; } /** * <p>@description: 得到前一天的开始日历 </p> * <p>@method: getLastDayStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastDayStartCalendar() { Calendar calendar = getHourStartCalendar(); //将日设置为前一天 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1); return calendar; } /** * <p>@description: 得到后一天的开始日历 </p> * <p>@method: getLaterDayStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterDayStartCalendar() { Calendar calendar = getHourStartCalendar(); //将日设置为后一天 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1); return calendar; } /** * <p>@description: 得到当前日的结束日历 </p> * <p>@method: getDayEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getDayEndCalendar() { Calendar calendar = getHourEndCalendar(); //将小时置23 calendar.set(Calendar.HOUR_OF_DAY, 23); return calendar; } /** * <p>@description: 得到前一日的结束日历 </p> * <p>@method: getLastDayEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastDayEndCalendar() { Calendar calendar = getDayEndCalendar(); //将日置前一日 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1); return calendar; } /** * <p>@description: 得到后一日的结束日历 </p> * <p>@method: getLaterDayEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterDayEndCalendar() { Calendar calendar = getDayEndCalendar(); //将日置后一日 calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1); return calendar; } /** * <p>@description: 得到当前月的开始日历 </p> * <p>@method: getMonthStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getMonthStartCalendar() { Calendar calendar = getDayStartCalendar(); //设置为1号 calendar.set(Calendar.DAY_OF_MONTH, 1); return calendar; } /** * <p>@description: 得到上个月的开始日历 </p> * <p>@method: getLastMonthStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastMonthStartCalendar() { Calendar calendar = getMonthStartCalendar(); //设置月为上一月 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); return calendar; } /** * <p>@description: 得到下个月的开始日历 </p> * <p>@method: getLaterMonthStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterMonthStartCalendar() { Calendar calendar = getMonthStartCalendar(); //设置月为下一月 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1); return calendar; } /** * <p>@description: 得到当前月的结束日历 </p> * <p>@method: getMonthEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getMonthEndCalendar() { Calendar calendar = getDayEndCalendar(); //设置为最后一天 calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); return calendar; } /** * <p>@description: 得到上一月的结束日历 </p> * <p>@method: getLastMonthEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastMonthEndCalendar() { Calendar calendar = getMonthEndCalendar(); //设置月为上一月 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); return calendar; } /** * <p>@description: 得到下个月的结束日历 </p> * <p>@method: getLaterMonthEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterMonthEndCalendar() { Calendar calendar = getMonthEndCalendar(); //设置月为下个月 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1); return calendar; } /** * <p>@description: 得到当前年的开始日历 </p> * <p>@method: getYearStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getYearStartCalendar() { Calendar calendar = getMonthStartCalendar(); //设置月为1月 calendar.set(Calendar.MONTH, 0); return calendar; } /** * <p>@description: 得到前一年的开始日历 </p> * <p>@method: getLastYearStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastYearStartCalendar() { Calendar calendar = getYearStartCalendar(); //设置年份为前一年 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1); return calendar; } /** * <p>@description: 得到后一年的开始日历 </p> * <p>@method: getLaterYearStartCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterYearStartCalendar() { Calendar calendar = getYearStartCalendar(); //设置年份为后一年 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1); return calendar; } /** * <p>@description: 得到当前年的结束日历 </p> * <p>@method: getYearEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getYearEndCalendar() { Calendar calendar = getMonthEndCalendar(); //设置月为12月 calendar.set(Calendar.MONTH, 11); //设置为31号 calendar.set(Calendar.DAY_OF_MONTH, 31); return calendar; } /** * <p>@description: 得到上一年的结束日历 </p> * <p>@method: getLastYearEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLastYearEndCalendar() { Calendar calendar = getYearEndCalendar(); //设置年为前一年 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1); return calendar; } /** * <p>@description: 得到后一年的结束日历 </p> * <p>@method: getLaterYearEndCalendar </p> * <p>@author: 枫铃也 </p> * <p>@since: 2019-10-09 14:48 </p> * * <p>@return java.util.Calendar </p> */ public static Calendar getLaterYearEndCalendar() { Calendar calendar = getYearEndCalendar(); //设置年为后一年 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1); return calendar; } public static void main(String[] args) { System.out.println("明年的开始:" + DateUtil.format(getLaterYearStartCalendar().getTime())); System.out.println("明年的结束:" + DateUtil.format(getLaterYearEndCalendar().getTime())); System.out.println("今年的开始:" + DateUtil.format(getYearStartCalendar().getTime())); System.out.println("今年的结束:" + DateUtil.format(getYearEndCalendar().getTime())); System.out.println("去年的开始:" + DateUtil.format(getLastYearStartCalendar().getTime())); System.out.println("去年的结束:" + DateUtil.format(getLastYearEndCalendar().getTime())); } }
2019年10月09日
61 阅读
0 评论
0 点赞
Java 8 的一些集合操作
将一个对象集合中的某一个字段取出来生成一个新的集合List<Store> storeList = storeService.listStore(page, size); List<Integer> collect = storeList.stream().map(s -> s.getStoreId()).collect(Collectors.toList()); //OR List<Integer> collect = storeList.stream().map(Store::getStoreId).collect(Collectors.toList());将List对象集合转化为key为对象ID的MapList<Specification> specifications = specificationService.listSpecification(); Map<Integer, Specification> collect = specifications.stream().collect(Collectors.toMap(Specification::getSpecificationId, Function.identity()));跟据某个属性分组Map<String, List<PersonData>> collect = list.stream().collect(Collectors.groupingBy(PersonData::getType));根据某个属性分组,汇总某个属性Map<String, Integer> collect2 = list.stream().collect(Collectors.groupingBy(PersonData::getType,Collectors.summingInt(PersonData::getAge)));根据某个属性添加条件过滤数据list = list.stream().filter(u -> !u.getType().equals("访客")).collect(Collectors.toList());判断一组对象里面有没有属性值是某个值boolean add = list.stream().anyMatch(m -> "王五".equals(m.getName()));
2019年10月02日
97 阅读
0 评论
0 点赞
日常开发规范
注:基于SonarLint 官方网址: SonarLint特殊记录HashMap的大小应该为目标大小/加载因子且为2^n 向上取整HashMap默认的加载因子是0.75 .它在时间和空间成本上寻求了一种折中。 如果只装载100个元素的HashMap没有特殊的用途,那么为了在时间和空间上达到最佳性能,HashMap的初始容量可以设为100/0.75 = 133.33。为了防止rehash,向上取整,为134。 但是还有另外一个问题,就是hash碰撞的问题。如果我们将HashMap的容量设置为134,那么如何保证其中的哈希碰撞会比较少呢? 除非重写hashcode()方法,否则,似乎没有办法保证。 那么这里不得不提HashMap如何为元素选择下标的方法了。static int indexFor(int h, int length) { return h & (length-1); }其中h为key哈希后得到的值,length为哈希表的长度。 134-1 = 128 + 6 -1; 那么 length-1的二进制值的最后3位为101; 假设这100个装载的元素中他们的key在哈希后有得到两个值(h),他们的二进制值除了低3位之外都相同,而第一个值的低3位为011,第二个值的低3位为001; 这时候进行java的&预算,011 & 101 = 001 ;001 & 101 = 001; 他们的值相等了,那么这个时候就会发生哈希碰撞。 除此之外还有一个更加严重的问题,由于在101中第二位是0,那么,无论我们的key在哈希运算之后得到的值h是什么,那么在&运算之后,得到的结果的倒数第二位均为0; 因此,对于hash表所有下标的二进制的值而言,只要低位第二位的值为1,(例如0010,0011,0111,1111)那么这个下标所代表的桶将一直是空的,因为代码中的&运算的结果永远不会产生低位第二位为1的值。这就大大地浪费了空间,同时还增加了哈希碰撞的概率。这无疑会降低HashMap的效率。 那么如何才能减少这种浪费呢?最佳的方法当然是让length-1的二进制值全部位均为1.那么length的值是多少合适呢? 没错,length=2^n。 只要将hash表的长度设为2的N次方,那么,所有的哈希桶均有被使用的可能。 与134最靠近的2^n无疑是128。 如果只修改HashMap的长度而不修改HashMap的加载因子的话,HashMap会进行rehash操作,这是一个代价很大的操作,所以不可取。 那么应该选择的就应该是256。 而由于空间加大和有效利用哈希桶,这时的哈希碰撞将大大降低,因此HashMap的读取效率会比较高。 所以,最后结论就是:HashMap的大小应该设置为256。 其实在Java中,无论你的HashMap(x)中的x设置为多少,HashMap的大小都是2^n。2^n是大于x的第一个数。因为HashMap的初始化代码中有以下这行代码:int capacity = 1; while (capacity < initialCapacity) capacity <<= 1;但是这就带来了一个问题,如果x=100,那么HashMap的初始大小应该是128.但是100/128=0.78,已经超过默认加载因子的大小了。因此会resize一次,变成256。所以最好的结果还是256。1. 字符串不应该在循环中使用'+'连接原:Strings are immutable objects, so concatenation doesn't simply add the new String to the end of the existing string. Instead, in each loop iteration, the first String is converted to an intermediate object type, the second string is appended, and then the intermediate object is converted back to a String. Further, performance of these intermediate operations degrades as the String gets longer. Therefore, the use of StringBuilder is preferred. 译:Sring是不可变的对象,所以在进行字符拼接的时候不只是将新的字符串添加到现有字符串的末尾。相反,在每个循环迭代中,先将第一个字符串转换为中间对象类型,再添加第二个字符串,然后将中间对象转换回字符串。此外,随着字符串变长,这些中间操作的性能会下降。因此,最好使用StringBuilder。//不规范代码示例 String str = ""; for (int i = 0; i < arrayOfStrings.length ; ++i) { str = str + arrayOfStrings[i]; } //规范代码示例 StringBuilder bld = new StringBuilder(); for (int i = 0; i < arrayOfStrings.length; ++i) { bld.append(arrayOfStrings[i]); } String str = bld.toString();拓展(1)String是Java的基础类,他可以定义少量的字符串(2)StringBuffer是对String的扩充,他可以拼接大量字符串,但是他的效率比较低,因为他是线程安全的(3)StringBuidder是对StringBuffer的拓展,他提高了效率,但是他是线程不安全的2. 不应该在打印输出或者是记录日志的时候进行运算原:Passing message arguments that require further evaluation into a Guava com.google.common.base.Preconditions check can result in a performance penalty. That's because whether or not they're needed, each argument must be resolved before the method is actually called. Similarly, passing concatenated strings into a logging method can also incur a needless performance hit because the concatenation will be performed every time the method is called, whether or not the log level is low enough to show the message. Instead, you should structure your code to pass static or pre-computed values into Preconditions conditions check and logging calls. Specifically, the built-in string formatting should be used instead of string concatenation, and if the message is the result of a method call, then Preconditions should be skipped altoghether, and the relevant exception should be conditionally thrown instead. 译:程序在调用方法之前,无论是否需要它们都将解析每一个参数并将需要进一步计算的消息参数传递到Guava 而com.google.common.base.Preconditions在检查中可能会导致性能损失。 类似的,将连接的字符串传递到日志方法也会导致不必要的性能损失,因为每次调用该方法时都会执行运算或者拼接,无论日志级别是否低到足以显示消息。 相反,应该构造代码,将静态值或预计算值传递到Preconditions条件检查和日志记录调用中。 具体来说,应该使用内置的字符串格式而不是字符串连接,如果消息是方法调用的结果,则应该跳过先决条件altoghether,而应该有条件地抛出相关异常。//不规范代码示例 // 即使日志级别过高,无法显示调试消息,也会执行字符串连接 logger.log(Level.DEBUG, "Something went wrong: " + message); logger.fine("An exception occurred with message: " + message); LOG.error("Unable to open file " + csvPath, e); Preconditions.checkState(a > 0, "Arg must be positive, but got " + a); //即使使用了判断,可当a>0的时候依旧需要进行拼接 Preconditions.checkState(condition, formatMessage()); Preconditions.checkState(condition, "message: %s", formatMessage()); //规范代码示例 logger.log(Level.SEVERE, "Something went wrong: {0} ", message); // 只有在需要时才应用字符串格式 logger.fine("An exception occurred with message: {}", message); // SLF4J, Log4j logger.log(Level.SEVERE, () -> "Something went wrong: " + message); // 从 Java 8 开始,我们可以使用Supplier,因为它是懒加载的 LOG.error("Unable to open file {0}", csvPath, e); if (LOG.isDebugEnabled() { LOG.debug("Unable to open file " + csvPath, e); } Preconditions.checkState(arg > 0, "Arg must be positive, but got %d", a); if (!condition) { throw new IllegalStateException(formatMessage()); // formatMessage()方法只在条件下调用 } if (!condition) { throw new IllegalStateException("message: " + formatMessage()); }拓展(1)supplier也是是用来创建对象的,但是不同于传统的创建对象语法:new。每次调用get()方法时都会调用构造方法创建一个新对象,示例代码:public class TestSupplier { private int age; TestSupplier(){ System.out.println(age); } public static void main(String[] args) { //创建Supplier容器,声明为TestSupplier类型,此时并不会调用对象的构造方法,即不会创建对象 Supplier<TestSupplier> sup= TestSupplier::new; System.out.println("--------"); //调用get()方法,此时会调用对象的构造方法,即获得到真正对象 sup.get(); //每次get都会调用构造方法,即获取的对象不同 sup.get(); } }运行结果:-------- 0 03.应该使用日志记录异常信息原:Throwable.printStackTrace(...) prints a Throwable and its stack trace to some stream. By default that stream System.Err, which could inadvertently expose sensitive information. Loggers should be used instead to print Throwables, as they have many advantages: ● Users are able to easily retrieve the logs. ● The format of log messages is uniform and allow users to browse the logs easily. This rule raises an issue when printStackTrace is used without arguments, i.e. when the stack trace is printed to the default stream. 译:Throwable.printStackTrace(...)将Throwable及其堆栈跟踪信息打印到某些流。 默认情况下,该流System.Err可能会无意间公开敏感信息。 应该使用记录器来打印Throwable,因为它们具有许多优点: ● 用户能够轻松检索日志。 ● 日志消息的格式统一,并且允许用户轻松浏览日志。 当使用不带参数的printStackTrace时(即,将堆栈跟踪打印到默认流时),此规则会引起问题。//不规范代码示例 try { /* ... */ } catch(Exception e) { e.printStackTrace(); } //规范代码示例 try { /* ... */ } catch(Exception e) { LOGGER.log("context", e); }
2019年09月27日
81 阅读
0 评论
0 点赞
日常开发Bug集锦
本篇内容将记录一些日常开发中的一些Bug出现情况和解决方案,长期更新SpringMVC报错:如果刚刚写了一个Controller,那记得在Controller上加上@ResponseBody注解java.lang.IllegalArgumentException: Unknown return value type: java.lang.Integer at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue在for循环中出现NullPoint异常:(如果是普通的for循环,那要先判断被循环的队列是否为空)切记不要在循环体内进行元素的增删,若需要在循环体内对元素进行增删,则使用迭代器操作(罪魁祸首在于元素的下标)MyBatiis中模糊搜索应该使用`name` LIKE "%"#{search}"%"或者`name` LIKE concat('%', #{search}, '%')SpringMVC接收Map的json数据时,出现String无法转换成int类型(即使key就是int类型)在json转化成bean的时候将key视为String类型
2019年09月26日
57 阅读
0 评论
0 点赞
2019-06-03
Android使用贝塞尔曲线画心形
一开始我只是想画个圆,可画着画着就成了心形,那就将错就错1. 创建一个Activity RelativeLayout container = findViewById(R.id.download_container); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); deviceWidth = metrics.widthPixels; deviceHeight = metrics.heightPixels; Circle circle = new Circle(this, deviceWidth / 2, deviceHeight / 2, deviceWidth / 8); Line line = new Line(this, deviceWidth / 2, deviceHeight / 2, deviceWidth / 8); container.addView(line);2. 创建一个自定义的Viewimport android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.view.View; public class Line extends View { private Paint mPaint; private PointF startPointF; private PointF endPointF; private PointF controlPointF1, controlPointF2; private PointF startPointF2; private PointF endPointF2; private PointF controlPointF3, controlPointF4; public Line(Context context, float x, float y, float radius) { super(context); double d = (2 * Math.sqrt(2) - 1); this.startPointF = new PointF(x, y - radius); this.endPointF = new PointF(x, y + radius / 10); this.controlPointF1 = new PointF(x, (float) (y - d * radius)); this.controlPointF2 = new PointF((float) (x + d * radius), (float) (y - d * radius)); this.startPointF2 = new PointF(x, y - radius); this.endPointF2 = new PointF(x, y + radius / 10); this.controlPointF3 = new PointF(x, (float) (y - d * radius)); this.controlPointF4 = new PointF((float) (x - d * radius), (float) (y - d * radius)); this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); this.mPaint.setColor(Color.WHITE); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制贝塞尔曲线 Path path = new Path(); path.moveTo(startPointF.x, startPointF.y); path.cubicTo(controlPointF1.x, controlPointF1.y, controlPointF2.x, controlPointF2.y, endPointF.x, endPointF.y); canvas.drawPath(path, mPaint); path.moveTo(startPointF2.x, startPointF2.y); path.cubicTo(controlPointF3.x, controlPointF3.y, controlPointF4.x, controlPointF4.y, endPointF2.x, endPointF2.y); canvas.drawPath(path, mPaint); } }运行效果
2019年06月03日
151 阅读
0 评论
0 点赞
1
2