一、java apis
-
优先级
- java sdk
- guava
- spring
- commons
-
java8 日期/时间库
-
时间运算
@Test public void compute() { LocalDate day = LocalDate.of(2018, 11, 11); LocalDate nextDay = day.plusDays(1); LocalDateTime now = LocalDateTime.of(2018, 11, 11, 8, 0, 0); LocalDateTime last = now.minusDays(1); Assert.assertTrue(nextDay.equals(LocalDate.of(2018, 11, 12))); Assert.assertTrue(last.equals(LocalDateTime.of(2018, 11, 10, 8, 0, 0))); }
-
新老库转换
@Test public void transform() { Timestamp t1 = new Timestamp(0); LocalDateTime ldt = t1.toLocalDateTime(); Timestamp t2 = Timestamp.valueOf(ldt); Assert.assertTrue(t1.getTime() == t2.getTime()); }
-
format
@Test public void format() { DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE; Assert.assertEquals("2018-11-11", dateFormatter.format(LocalDate.of(2018, 11, 11))); }
-
parse
@Test public void parse() { DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate day = LocalDate.parse("1900-01-01", dateFormatter); Assert.assertEquals(LocalDate.of(1900, 1, 1), day); }
-
spring mvc
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>
@Bean public SimpleModule jsr310JacksonModule() { return ObjectMapper2.java8DateTimeModule(); } public static SimpleModule java8DateTimeModule() { SimpleModule javaTimeModule = new SimpleModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER)); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DATE_TIME_FORMATTER)); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_DATE)); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_DATE)); javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_TIME)); javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_TIME)); return javaTimeModule; }
-
spring data jpa
@Bean @Qualifier(UNIT_NAME) public LocalContainerEntityManagerFactoryBean nodeEntityManagerFactory( @Qualifier(UNIT_NAME) DataSource nodeDataSource, EntityManagerFactoryBuilder builder, JpaProperties jpaProperties) { return builder.dataSource(nodeDataSource) .packages(Node.class, Jsr310JpaConverters.class) .persistenceUnit(UNIT_NAME) .properties(jpaProperties.getHibernateProperties(nodeDataSource)) .build(); }
-
-
java8 stream
-
变换
public static <T> List<T> filter(Collection<T> unfiltered, Predicate<T> predicate) { return unfiltered.stream().filter(predicate).collect(Collectors.toList()); } public static <T> List<T> reject(Collection<T> unfiltered, Predicate<T> predicate) { return filter(unfiltered, predicate.negate()); } public static <F, T> List<T> map(Collection<F> from, Function<? super F, T> mapper) { return from.stream().map(mapper).collect(Collectors.toList()); } public static <K, V, F> Map<K, V> toMap(Collection<F> list, Function<F, K> keyMapper, Function<F, V> valueMapper) { return list.stream().collect(Collectors.toMap(keyMapper, valueMapper)); } public static <K, T> Map<K, List<T>> groupBy(Collection<T> list, Function<? super T, ? extends K> classifier) { return list.stream().collect(Collectors.groupingBy(classifier, Collectors.toList())); }
-
计算/其他
public static <S> BigDecimal sum(Collection<S> src, Function<S, BigDecimal> valueFn) { return src.stream().map(valueFn).reduce(BigDecimal.ZERO, BigDecimal::add); } @Test public void range() { int sum = IntStream.range(1, 3).sum(); Assert.assertTrue(3 == sum); }
-
-
java8 Optional
public T orElse(T other) { return value != null ? value : other; } public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get(); }
-
Strings
-
Joiner/Splitter
@Test public void splitter() { Splitter splitter = Splitter.on(",").omitEmptyStrings().trimResults(); List<String> list = splitter.splitToList("1,,,1,1 ,"); Assert.assertEquals(list, Arrays.asList("1", "1", "1")); }
-
Padding
@Test public void padding() { String s1 = Strings.padStart("abc", 5, '0'); String s2 = Strings.padEnd("abc", 5, '0'); Assert.assertEquals("00abc", s1); Assert.assertEquals("abc00", s2); }
-
Strings#isNullOrEmpty vs StringUtils#isBlank
-
-
Lists
-
partition
@Test public void partition() { List<String> list = IntStream.range(0, 123123).mapToObj(String::valueOf).collect(Collectors.toList()); List<List<String>> pts = Lists.partition(list, 10); Assert.assertTrue(pts.size() == 123123 / 10 + 1); }
-
-
Sets
-
intersection
@Test public void intersection() { Set<Integer> s1 = Sets.newHashSet(1, 2, 3); Set<Integer> s2 = Sets.newHashSet(1, 3, 5); Assert.assertTrue(Sets.intersection(s1, s2).contains(3)); }
-
difference
@Test public void difference() { Set<Integer> s1 = Sets.newHashSet(1, 2, 3); Set<Integer> s2 = Sets.newHashSet(1, 3, 5); Assert.assertTrue(Sets.difference(s1, s2).contains(2)); }
-
-
Maps
-
ImmutableMap
@Test public void immutableMap() { ImmutableMap<String, String> im = ImmutableMap.of("k1", "v1"); Assert.assertEquals("v1", im.get("k1")); }
-
putIfAbsent
@Test public void putIfAbsent() { Map<String, String> m = new HashMap<>(); m.put("k1", "v1"); m.putIfAbsent("k1", "v11"); m.putIfAbsent("k2", "v2"); Assert.assertEquals("v1", m.get("k1")); Assert.assertEquals("v2", m.get("k2")); }
-
getOrDefault
@Test public void getOrDefault() { Map<String, String> m = new HashMap<>(); m.put("k1", "v1"); Assert.assertEquals("v2", m.getOrDefault("k2", "v2")); }
-
@deprecated - Maps.newHashMap(), Maps.newConcurrentHashMap()
-
difference
-
-
Iterables
- Iterables#concat
- Iterables#getFirst(Iterable<? extends T> iterable, @Nullable T defaultValue)
- Iterables#getLast
-
Objects
- equals
-
Comparator, Ordering
-
Ordering#natural vs Comparator#naturalOrder
@Test public void naturalOrder() { List<Integer> numbers = Arrays.asList(3, 5, 1, 2, 6); List<Integer> st1 = Ordering.natural().sortedCopy(numbers); List<Integer> st2 = Lists.newArrayList(numbers); st2.sort(Comparator.naturalOrder()); Assert.assertEquals(st1, st2); Assert.assertNotEquals(numbers, st2); }
-
-
Preconditions
Preconditions.checkArgument(flag, "%s is xxx", "flag"); Preconditions.checkNotNull(flag, "%s is xxx", "flag");
-
Guava Range
@Test public void range() { Range<Integer> range = Range.open(1, 10); Assert.assertTrue(range.contains(2)); }
-
Guava Cache - CacheBuilder.newBuilder()
-
Files/IoUtils, Hashing
二、java exceptions
必须遵守原则
- 不要仅仅捕获异常而不做任何处理,避免empty catch和没有意义的异常message
- 在能处理异常的情况下捕获异常,否则Catch Late
- 不要多次重复记录同一个异常
推荐原则
- 对于肯定不会出现的 checked exception,在最底层抓住它,然后抛出 AssertionError,例如 UnsupportedEncodingException,我们要尽早抓住它,然后重新抛出 throw new AssertionError(e)
- 自己定义异常时,推荐使用 Runtime 异常而不是 Checked 异常
- 应该捕获指定的异常,而不是 catch(Exception e) 了事
这对性能、代码的可读性以及诸多方面都有好处 - 尽早抛出异常,减少无意义的堆栈信息,快速的定位问题
- 尽量不要二次抛出异常
如果非得这么做的话,抛出同一个异常示例,而不是重新构建一个异常对象,这对性能是有帮助的,而且外层调用者可获取真实的异常信息 - 设计异常处理策略,而不是直接throw和catch多个异常,我们可以自定义异常包含error code并且调用者可以处理这个error code,建议创建一个公共类去处理这些code
- 不使用异常来管理业务逻辑
如果一个控制逻辑可通过 if-else 语句来简单完成的,那就不用使用异常,因为异常会降低代码的可读性和性能,例如一些 null 的判断逻辑、除0的控制等等; - 当方法判断出错该返回时应该抛出异常,而不是返回一些错误值
因为错误值难以理解而且不够直观,例如抛出 FileNotFoundException 异常,而不是返回 -1 或者 -2 之类的错误值。 - Null 的判断逻辑并不是一成不变的
当方法允许返回 null 的时候使用 if-else 控制逻辑,否则就抛出 NullPointerException - 大部分情况下不建议在循环中进行异常处理,应该在循环外对异常进行捕获处理
- 释放资源
请使用 finally 来释放一些打开的资源或使用try-with-resources,例如打开的文件、数据库连接等等 - 异常命名约定
当我们自定义异常的时候,确保它以Exception结尾,还要确保它的package包像JDK自带的异常那样,比如IOException是所有IO操作Exception的基类 - 异常是昂贵的
有时候我们不需要抛出异常,只需要返回个boolean值告诉调用者成功或失败,比如我们调用第三方的服务,我们可能希望避免抛出错误,当连接失败的时候 - 使用javadoc @throws 明确method抛出的异常是非常有用的当你给其他应用提供接口的时候
三、java logger
-
日志五个级别
- 错误级别(ERROR) --指系统发生了严重的问题,系统无法自行恢复,需要立刻调查,例如: NPE, 数据库不可用等
- 警告级别(WARN) --指系统可以继续运行,但是存在潜在风险,一般而言,高可靠的系统应该具备平滑处理警告事件的能力。警告日志例子包括,接收到错误参数而改用默认值,达到运行最大线程数而抛弃当前
- 信息级别(INFO) --重要信息点,这些信息对于问题定位、数据分析应该提供重要帮助。例如:定期启动的任务事件
- 调试级别(DEBUG) -- 系统运行的详细日志,包括参数值的打印
- 跟踪级别(TRACE) --更加详细的日志,一般而言,用于客户端产品的收集。
-
使用MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能
//线程或拦截器开始的地方 MDC.put("username",currentUser.getUsername()); 在日志配置文件中通过“%X{username}”获取
-
设置scan="true" scanPeriod="60 seconds"
-
slf4j-jcl-<version>.jar包和jcl-over-slf4j-<version>.jar不能同时出现,会死循环
-
maven项目中将logback-test.xml放在src/test/resources中,logback.xml用于产品环境放在服务器上
-
日志配置文件中%d{MM-dd-yyyy}要包含yyyy,一般放在后面
-
产品不配置ConsoleAppender,这个仅开发环境使用
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="UTF-8"> <pattern>%d{HH:mm:ss.SSS} [%thread][%logger{0}][%X{user}] %-5level - %msg%n</pattern> </encoder> </appender>
-
为指定功能配置独立的Appender,需要增加 additivity="false"以保证不叠加root的appender(具体看需求)
<logger name="org.springframework" level="INFO" additivity="false"> <appender-ref ref="RollingFile"/> </logger>
-
异常对象放最后一位,且不需要占位符
logger.error("error",e);
网友评论