# feilong亮点

1. 有常用专属工具类 (如处理日期的 `DateUtil`,处理集合的 `CollectionsUtil`,类型转换的`ConvertUtil` 等等等)
2. 有常用JAVA常量类 (如日期格式 `DatePattern`, 时间间隔 `TimeInterval` 等等等)
3. 不必要的`Exception` 转成`RuntimeException`,减少不必要的代码
4. 国内`中文注释`最完善的API
5. 有完善的单元测试

## 1."看一眼就会爱上他"的方法

### 1.1 ConvertUtil.toList(T...)

曾经,你调用某个api时,该api需要一个list参数, 但是你现在只有`单对象`

你需要这么写

```java
List<Long> itemIds = new ArrayList<>();
itemIds.add(itemId);

sdkItemManager.findItemImageByItemIds(itemIds);
```

总感觉怪怪的, **很烦人**

你现在可以这么写

```java
sdkItemManager.findItemImageByItemIds(ConvertUtil.toList(itemId));
```

一行代码,**轻松快乐的**写代码

同样,下面的代码

```java
List<Long> skuIds = new ArrayList<>();
skuIds.add(9L);
skuIds.add(10L);
skuIds.add(13L);
skuIds.add(18L);
skuIds.add(20L);
BundleValidateResult result = bundleManager.validateBundle(skuIds);
```

依然,可以简写

```java
List<Long> skuIds=ConvertUtil.toList(9L, 10L, 13L, 18L, 20L);
BundleValidateResult result = bundleManager.validateBundle(skuIds);
```

代码的可读性更高,**更简洁**

**PS:** 如果使用 [import static](https://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html) 代码可以`更简洁`

### 1.2 CollectionsUtil.getPropertyValueList(Collection, String)

> 循环集合 `objectCollection`,取到对象指定的属性 `propertyName` 的值,拼成 `List`(ArrayList).

很多场合下,手头上有 `bean list`, 但是操作的时候,你可能需要使用每个bean里面的某个属性

**比如:** 提取SalesOrderCommand list里面的id属性组成 `List<Long>`

```java
List<SalesOrderCommand> salesOrderPage = sdkOrderDao.findOrdersWithOutPage(sorts, searchParam);

//...

List<Long> idList = new ArrayList<>(salesOrderPage.size());
for (SalesOrderCommand cmd : salesOrderPage){
    idList.add(cmd.getId());
}

//查询订单行
List<OrderLineCommand> allLineList = sdkOrderLineDao.findOrderDetailListByOrderIds(idList);
```

这段代码,可以一行代码搞定

```java
List<SalesOrderCommand> salesOrderPage = sdkOrderDao.findOrdersWithOutPage(sorts, searchParam);

//...

List<Long> idList =CollectionsUtil.getPropertyValueList(salesOrderPage, "id");

//查询订单行
List<OrderLineCommand> allLineList = sdkOrderLineDao.findOrderDetailListByOrderIds(idList);
```

**PS:** 相似的方法,还有 `CollectionsUtil.getPropertyValueSet(Collection<O>, String)` 以及 `CollectionsUtil.getPropertyValueMap(Collection<O>, String, String)`

## 2.不能不说的异常处理

众所周知,JAVA 有 `checked exception` 和 `uncheckedException` 之分,也就是我们常说的 `RuntimeException`和 `Exception`

`checked exception`有其使用场景,但是我们日常开发过程中,并没有对他做特殊的代码处理

比如,大部分小伙伴的代码是这样的:

```java
public ContactCommand toContactCommand(ContactCommand command) {
	try {
		BeanUtils.copyProperties(command, this);
	} catch (Exception e){
		LOGGER.error("", e);
		//or e.printStackTrace();
	}
	return command;
}
```

其实细究下来,上述代码是**不合理**的, 如果转换的时候出现了异常,这里就会出现数据没有转换过去的情况,

这理论上是 `RuntimeException`,但是 `org.apache.commons.beanutils.BeanUtils` 里面使用的是`Exception`, 所以小伙伴不能不`try... catch`一下,可是 catch 代码里面有可能仅仅写了log记录,这有可能会出现逻辑问题 `(本来需要抛出异常让事务回滚)`

这时可以使用 `com.feilong.core.bean.BeanUtil`

```java
public ContactCommand toContactCommand(ContactCommand command){
    com.feilong.core.bean.BeanUtil.copyProperties(command, this);
    return command;
}
```

当然,如果你确定copy的对象相同属性名称的`类型是一致`的, 你可以使用 `PropertyUtil` ,可以有效的避免不必要的类型转换,提高效率

**代码简洁**,而且内部包装成的是自定义的 `BeanOperationException`(`RuntimeException`),如果需要特殊处理,依然可以 `try...catch...`

## 3. 有丰富的javadoc

调用方法的时候,可以清晰的感知这个方法的 `作用`,`示例`,`说明点`,`参数`,`返回值`,`异常`等信息

![](http://i.imgur.com/DG9X6vp.png)

**源码示例:**

```java
/**
 * 计算两个时间相差的的天数(<span style="color:red">绝对值</span>).
 * 
 * <h3>说明:</h3>
 * <blockquote>
 * <p>
 * 值=两个时间相差毫秒的绝对值/{@link TimeInterval#MILLISECOND_PER_DAY}
 * </p>
 * </blockquote>
 * 
 * <h3>示例:</h3>
 * 
 * <blockquote>
 * 
 * <pre class="code">
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2008-08-24",COMMON_DATE),
 *      toDate("2008-08-27",COMMON_DATE)) = 3
 * 
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-08-21 12:00:00",COMMON_DATE_AND_TIME),
 *      toDate("2016-08-22 11:00:00",COMMON_DATE_AND_TIME)) = 0
 * 
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-08-21",COMMON_DATE),
 *      toDate("2016-08-22",COMMON_DATE)) = 1
 *      
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-02-28",COMMON_DATE),
 *      toDate("2016-03-02",COMMON_DATE)) = 3
 * 
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-08-31",COMMON_DATE),
 *      toDate("2016-09-02",COMMON_DATE)) = 2
 * 
 * </pre>
 * 
 * </blockquote>
 * 
 * @param date1
 *            date1
 * @param date2
 *            date2
 * @return 如果 <code>date1</code> 是null,抛出 {@link NullPointerException}<br>
 *         如果 <code>date2</code> 是null,抛出 {@link NullPointerException}
 * @see #getIntervalTime(Date, Date)
 * @see #getIntervalDay(long)
 * @since 1.6.0
 */
public static int getIntervalDay(Date date1,Date date2){
    return getIntervalDay(getIntervalTime(date1, date2));
}
```

如果你使用maven的话,只需要在依赖的jar 右键, maven--> `download javadoc` 或者 `download sources` 会自动下载

![](http://i.imgur.com/Ia3ZKpY.png)

## 4. 每个方法均有完善的 junit test

> 方法实现之后,有上述的javadoc 详细的描述这个方法的作用 特点,注意点等, 那么怎么证明你写的东西都是正确而胡编乱造的呢?

我们有详细的 `junit` 单元测试, 每次构建的时候,都会经过maven 的单元测试周期

比如 `MapUtilGetSubMapTest`

```java
package com.feilong.core.util.maputiltest;

import static java.util.Collections.emptyMap;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import com.feilong.core.util.MapUtil;

public class MapUtilGetSubMapTest{

    @Test
    public void testGetSubMap(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        Map<String, Integer> subMap = MapUtil.getSubMap(map, "a", "c");
        assertThat(subMap, allOf(hasEntry("a", 3007), hasEntry("c", 3001), not(hasKey("b")), not(hasKey("d"))));
    }

    @Test
    public void testGetSubMap1(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        Map<String, Integer> subMap = MapUtil.getSubMap(map, "a", "c", "f");
        assertThat(subMap, allOf(hasEntry("a", 3007), hasEntry("c", 3001), not(hasKey("b")), not(hasKey("d"))));
    }

    @Test
    public void testGetSubMapNullKeys(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        assertEquals(map, MapUtil.getSubMap(map, null));
    }

    @Test
    public void testGetSubMapEmptyKeys(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        assertEquals(map, MapUtil.getSubMap(map));
    }

    @Test
    public void testGetSubMapNullMap(){
        assertEquals(emptyMap(), MapUtil.getSubMap(null, "a", "c"));
    }

    @Test
    public void testGetSubMapEmptyMap(){
        assertEquals(emptyMap(), MapUtil.getSubMap(new HashMap<>(), "a", "c"));
        assertEquals(emptyMap(), MapUtil.getSubMap(emptyMap(), "a", "c"));
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://feilong.gitbook.io/feilong-docs/feilong-liang-dian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
