位运算
位运算常用六种运算符
& 按位与, 同1为1| 按位或, 同0位0^ 异或,两个位相同为0,相异为1~ 取反,0转1,1转0>> 右移,Java中右移,符号位不变,左边补上符号位<< 左移,各二进位全部左移若干位,高位丢弃,低位补0
常用业务场景有:判断奇偶数,判断是否为2的整数次幂,左移,右移,两数交换,取相反数,取绝对值。
//====位运算 private void bitOperation() { int n = -8, m = 8; System.out.println("是否为奇数:" + ((n & 1) == 1)); System.out.println("是否为2的整数次幂:" + ((n & (n - 1)) == 0)); System.out.println("左移动:" + (n << 1)); System.out.println("右移动:" + (n >> 1)); System.out.println("无符号右移动:" + (n >>> 1)); System.out.println("因为左移是右测补0,不存在符号问题,所以不存在无符号左移动,"); //交换 n ^= m; m ^= n; n ^= m; System.out.println("交换后n=" + n + ",m=" + m); System.out.println("相反数n=" + (~n + 1)); // >> 31得到符号位 System.out.println("绝对值m=" + ((m ^ (m >> 31)) - (m >> 31))); //任何整数和自己异或的结果为 0,任何整数与 0 异或其值不变 }
时间处理
在Java8中提供了LocalDateTime和LocalDate,其中LocalDateTime用于处理日期时间,LocalDate用于处理日期。
常用业务有:格式化日期,判断周几,获取上一个周几,获取两日期之间时间间隔,获取两日期之间工作日
//====处理日期 private void handlerDate() { //======格式化日期 DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); DateTimeFormatter dfd = DateTimeFormatter.ofPattern("yyyy-MM-dd"); //当前时间 注意LocalDateTime为final LocalDateTime ldt = LocalDateTime.now(); System.out.println(df.format(ldt)); //自定义日期时间 ldt = LocalDateTime.parse("2020-05-20T10:15:30"); System.out.println(df.format(ldt)); //======判断是周几 System.out.println("周" + ldt.getDayOfWeek().getValue()); //======获取上一个周四 while (ldt.getDayOfWeek() != DayOfWeek.THURSDAY) { ldt = ldt.plusDays(-1); } System.out.println("上一个周四时间:" + df.format(ldt)); //======时间间隔 Duration duration = Duration.between(ldt, LocalDateTime.now()); System.out.println("相差" + duration.toDays() + "日"); System.out.println("相差:" + duration.toHours() + "小时"); System.out.println("相差:" + duration.toMinutes() + "分钟"); System.out.println("相差:" + duration.toMillis() + "毫秒"); //=======获取日期之间的工作日 List list = new ArrayList<>(); while (ldt.isBefore(LocalDateTime.now())) { if (ldt.getDayOfWeek() != DayOfWeek.SUNDAY && ldt.getDayOfWeek() != DayOfWeek.SATURDAY) { list.add(dfd.format(ldt)); } ldt = ldt.plusDays(1); } System.out.println(list); }
集合处理
集合List使用十分常见,对于集合处理常见业务场景有:自然排序,倒叙,中文排序,数据过滤,去重,转Map分组,分组统计
Map中常用场景为遍历
//===处理List private void handlerList() { //=====List List list = Arrays.asList("1,2,1,3,4,5".split(",")); //排序 List temp = list.stream().sorted((o1, o2) -> { //倒序 return o2.compareTo(o1); }).collect(Collectors.toList()); System.out.println(temp); //中文排序 List words = Arrays.asList("每,天,学,J,A,V,A".split(",")); temp = words.stream().sorted((o1, o2) -> { //倒序 return Collator.getInstance(Locale.CHINESE).compare(o1, o2); }).collect(Collectors.toList()); System.out.println(temp); //将字段为 1 的数据过滤掉 temp = list.stream().filter(s -> !s.equals("1")).collect(Collectors.toList()); System.out.println(temp); //去重 temp = list.stream().distinct().collect(Collectors.toList()); System.out.println(temp); //转Map Map> map2 = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.toList())); System.out.println(map2); //分组计数 Map map = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); System.out.println(map); } //===处理Map private void handlerMap() { //=====Map //遍历Map Map map = new HashMap<>(); Set> entries = map.entrySet(); for (Map.Entry entrie : entries) { System.out.println(entrie.getKey()); System.out.println(entrie.getValue()); } }
反射
日常开发中,反射也是常用手段,通常通过反射获取对象的字段,方法,字段赋值,方法调用,利用注解对字段进行注入等操作.
//====反射 private void handerReflect() throws IllegalAccessException, InvocationTargetException { //获取所有字段 Class> clazz = this.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("字段名称:" + field.getName()); System.out.println("字段类型:" + field.getType().toString()); System.out.println("是否为接口:" + field.getType().isInterface()); System.out.println("字段注解数量:" + field.getDeclaredAnnotations().length); //赋值 field.setAccessible(true); field.set(this, "每天学Java"); System.out.println("字段值:" + field.get(this)); } //获取所有的方法 Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println("方法名称:" + method.getName()); System.out.println("方法返回类型:" + method.getReturnType()); System.out.println("方法参数:" + method.getParameterTypes()); //调用 method.invoke() } }
线程池构建
通常我们会通过Executors来创建线程池,但是其底层也是使用ThreadPoolExecutor,面试中关于ThreadPoolExecutor的参数构造也是常见的面试题
//====线程池 private ThreadPoolExecutor threadPool() { //核心线程数量 int corePoolSize = 5; //最多线程数 int maximumPoolSize = 10; //非核心线程保活时间 long keepAliveTime = 1; //保活单位 TimeUnit unit = TimeUnit.MINUTES; //阻塞队列 BlockingQueue workQueue = new LinkedBlockingQueue<>(); //创建线程工厂类 ThreadFactory threadFactory = Executors.defaultThreadFactory(); //拒绝策略 RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler ); return threadPoolExecutor; }
线程同步工具类
使用多线程的目的是为了实现异步,但特定场景下,我们想要局部异步,最终同步,比如使用多个线程统计每个省份的用户量,最终通过线程同步工具类其聚合。
//====线程同步工具 private void latchUtil() throws InterruptedException { //CountDownLatch 一次控制 Executor executor = threadPool(); CountDownLatch latch = new CountDownLatch(5); for (int i = 0; i < 5; i++) { executor.execute(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 运行"); latch.countDown(); }); } System.out.println("等待所有线程执行结束"); latch.await(1, TimeUnit.MINUTES); System.out.println("所有线程执行结束"); //CyclicBarrier 循环多次控制 CyclicBarrier cyclicBarrier = new CyclicBarrier(5); for (int i = 0; i < 5; i++) { executor.execute(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } try { System.out.println(Thread.currentThread().getName() + " 第一批次运行"); cyclicBarrier.await(); System.out.println(Thread.currentThread().getName() + " 第二批次运行 "); cyclicBarrier.await(); System.out.println("结束"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }); } ((ExecutorService) executor).shutdown(); }
Excel解析
使用Excel完成批量导入功能是常见的功能,通过我们会利用POI包来实现这一功能,具体过程:拿到文件流,对Excel每一个Sheet页的字段进行校验,整理,保存,最终进行导入。
依赖:
org.apache.poi poi 3.11-beta2org.apache.poi poi-ooxml 3.11-beta2
代码过长,建议收藏哦!
//解析Excel表格 private void handlerExcel(String filePath, boolean isLocal) throws IOException, InvalidFormatException { InputStream inputStream = null; if (isLocal) { inputStream = new FileInputStream(new File(filePath)); } else { URL url = new URL(filePath); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.setReadTimeout(50000); inputStream = urlConnection.getInputStream(); } Workbook workbook = WorkbookFactory.create(inputStream); handlerSheet(workbook); } private void handlerSheet(Workbook workbook) { //sheet页面数量 int sheets = workbook.getNumberOfSheets(); Sheet currentSheet = null; for (int i = 0; i < sheets; i++) { Map field = new HashMap<>(); List objects = new ArrayList<>(); currentSheet = workbook.getSheetAt(i); System.out.println("处理sheet页面:" + currentSheet.getSheetName()); System.out.println("sheet页面行数" + (currentSheet.getLastRowNum() - currentSheet.getFirstRowNum())); //获取第一行表头字段 tableHead(field, currentSheet); //获取内容 for (int j = 1; j <= currentSheet.getLastRowNum(); j++) { Object o = tableContent(field, currentSheet.getRow(j)); objects.add(o); } //TODO:得到完整对象,进入验证导入 } } private void tableHead(Map field, Sheet sheet) { Row row = sheet.getRow(0); int cellIndex = 0; for (Cell cell : row) { //全部以字符串形式读取 cell.setCellType(Cell.CELL_TYPE_STRING); String name = getValue(cell).toString(); //TODO:可以name转换为key,后面通过反射进行注入 field.put(cellIndex++, name); } } private Object tableContent(Map fieldMap, Row row) { int cellIndex = 0; //TODO:替换为自定义对象字段,或使用Map返回,由调用方进行set Object o = new Object(); for (Cell cell : row) { //全部以字符串形式读取 cell.setCellType(Cell.CELL_TYPE_STRING); //获取单元格名称 String value = getValue(cell).toString(); //获取字段名称 String fieldName = fieldMap.get(cellIndex++); Field field = null; try { field = o.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(o, value); } catch (NoSuchFieldException e) { System.out.println("字段不存在:" + fieldName); e.printStackTrace(); } catch (IllegalAccessException e) { System.out.println("赋值字段不合法:" + field.getType() + "