我是一名初级开发人员,对Java流的使用经验很少。我已经确定(通过一些额外的日志记录),下面的流正在删除一条我正在寻找的记录,但我不知道为什么。请注意,我没有编写此代码,而这样做的人已离开公司。该项目正在使用Spring。
ConfirmCode表的结构如下:
Name Type Length Not Null
confirm_code_id int 11 True
account_id varchar 20 False
product_id varchar 20 False
dimension varchar 55 False
confirm_code int 1 False
confirm_desc varchar 50 False
action_enum enum 0 False
sms_keywords varchar 255 False
此表包含特定的枚举,根据设计,account_id,product_id和维度允许为空:
ConfirmCode
accountId productId dimension code desc enum keywords
2 Need to Reschedule RESCHED {not important}
7 Call Transferred TRANSFER {not important}
-1 Help HELP {not important}
-2 Opt In OPT IN {not important}
-3 Opt Out OPT OUT {not important}
-4 Response RESPONSE {not important}
1 Confirmed CONFIRM {not important}
但是,默认情况下,客户(accountID)可以覆盖绑定到枚举的代码。例如:
ConfirmCode
accountId productId dimension code desc enum keywords
704442 RemindMe Appointment Reminder 2 Confirmed CONFIRM {not important}
由于accountId,productId和Dimension允许为空,因此Spring运行的查询需要考虑到这一点,并且客户需要覆盖默认值,如您在上面看到的那样(在这种情况下,父帐户为null)。 / p>
Query:
public interface ConfirmCodeRepository extends JpaRepository<ConfirmCode, Long> {
@Query("SELECT c FROM ConfirmCode c WHERE (accountId is null OR accountId = :parentAccountId OR accountId = :accountId) "
+ " AND (productId = :productId OR productId is NULL)"
+ " AND (dimension is null OR dimension = :dimension)")
public List<ConfirmCode> findByAccountIdAndProductIdAndDimension(
@Param("accountId") String accountId, @Param("parentAccountId") String parentAccountId,
@Param("productId") String productId, @Param("dimension") String dimension);
我遇到的问题是,当为客户704442查询ConfirmCode表时,将为该客户返回该记录,但是在经过流中的Comparator代码之后,该记录将被删除。仅accountId,productId和Dimension为空的记录。这是对查询结果集进行逻辑处理的代码:
@Repository
public class ConfirmCodeDAO {
@Autowired
ConfirmCodeRepository confirmCodeRepo;
private static final Logger logger = LoggerFactory.getLogger(PreferenceService.class);
public Set<ConfirmCode> findByAccountIdAndParentAccountIdAndProductIdAndDimension(
String accountId,
String parentAccountId, String productId, String dimension) {
List<ConfirmCode> list = confirmCodeRepo
.findByAccountIdAndProductIdAndDimension(accountId, parentAccountId, productId,
dimension);
list.forEach(r -> logger.info("list: " + r.toString()));
Set<ConfirmCode> set = confirmCodeRepo
.findByAccountIdAndProductIdAndDimension(accountId, parentAccountId, productId,
dimension)
.stream()
.sorted(Comparator.comparing(ConfirmCode::getActionEnum,
Comparator.nullsFirst(Comparator.naturalOrder())))
.sorted(Comparator.comparing(ConfirmCode::getDimension,
Comparator.nullsFirst(Comparator.naturalOrder())))
.sorted(Comparator.comparing(ConfirmCode::getProductId,
Comparator.nullsFirst(Comparator.naturalOrder())))
.sorted(Comparator.comparing(ConfirmCode::getAccountId,
Comparator.nullsFirst(Comparator.reverseOrder())))
.collect(Collectors.toMap(ConfirmCode::getConfirmCode, confirmCode -> confirmCode,
(c1, c2) -> c2))
.entrySet()
.stream()
.map(e -> e.getValue())
.collect(Collectors.toSet());
set.forEach(r -> logger.info("set2: " + r.toString()));
return set;
}
}
以下是“列表”对象的日志记录:
Calling confirmCodeDAO with: 704442, parentAccountId: null, productId: RemindMe, dimension: Appointment Reminder
list: [accountId=704442, productId=RemindMe, dimension=Appointment Reminder, confirmCode=2, confirmDesc=Confirmed, actionEnum=CONFIRM, smsKeywords={not important}]
list: [accountId=null, productId=null, dimension=null, confirmCode=1, confirmDesc=Confirmed, actionEnum=CONFIRM, smsKeywords={not important}]
list: [accountId=null, productId=null, dimension=null, confirmCode=2, confirmDesc=Need to Reschedule, actionEnum=RESCHED, smsKeywords={not important}]
list: [accountId=null, productId=null, dimension=null, confirmCode=7, confirmDesc=Call Transferred, actionEnum=TRANSFER, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=3, confirmDesc=Repeat, actionEnum=REPEAT, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-1, confirmDesc=Help, actionEnum=HELP, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-2, confirmDesc=Opt In, actionEnum=OPT IN, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-3, confirmDesc=Opt Out, actionEnum=OPT OUT, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-4, confirmDesc=Response, actionEnum=RESPONSE, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-5, confirmDesc=Cancelled, actionEnum=CANCEL, smsKeywords={not important}, account=null, responseType=null]
以下是“设置”对象的日志记录:
set: [accountId=null, productId=null, dimension=null, confirmCode=-1, confirmDesc=Help, actionEnum=HELP, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=1, confirmDesc=Confirmed, actionEnum=CONFIRM, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=-5, confirmDesc=Cancelled, actionEnum=CANCEL, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=7, confirmDesc=Call Transferred, actionEnum=TRANSFER, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=3, confirmDesc=Repeat, actionEnum=REPEAT, smsKeywords={not important}, account=null, responseType=null]
set: [accountId=null, productId=null, dimension=null, confirmCode=-2, confirmDesc=Opt In, actionEnum=OPT IN, smsKeywords={not important}, account=null, responseType=null]
set: [accountId=null, productId=null, dimension=null, confirmCode=-4, confirmDesc=Response, actionEnum=RESPONSE, smsKeywords={not important}, account=null, responseType=null]
set: [accountId=null, productId=null, dimension=null, confirmCode=-3, confirmDesc=Opt Out, actionEnum=OPT OUT, smsKeywords={not important}, account=null, responseType=null]
您可以看到在查看流代码之后,我需要的记录被删除了。请为此提供建议,并感谢您的宝贵时间!
答案 0 :(得分:0)
排序的本身不能删除元素。但是通过使用
收集列表toMap.collect(Collectors.toMap(ConfirmCode::getConfirmCode, confirmCode ->
confirmCode, (c1, c2) -> c2))
每个属性的confirmCode只保留一个。
此toMap收集器的工作方式如下:
第一个参数定义了键,因此它将对象ConfigmCode的属性ConfirmCode作为键(名称有点误导)。第二个是值confirmCode -> confirmCode
,因此整个对象都保留为值。因此,我们得到一个Map<Integer, ConfirmCode>
。
第三参数描述了如果地图中存在关键区域,那么如何合并两个值。函数(c1,c2) -> c2
简单地说:采用第二个。
在您的列表中,第一个和第三个元素都具有confirmCode = 2,因此,仅第二个元素保留在地图中。
正如评论中所讨论的那样,由于比较器首先将null排序,因此这仅会丢弃第二个元素(在输入列表中),其confirmItem = 2。
现在,映射包含预期的元素,但是当将值收集到一组中时,ConfirmCode的equals方法将定义为相等的对象(如果它们具有相同的actionEnum)。虽然第一个元素(排序到末尾)具有与列表中第二个元素相同的actionEnum,但收集器仅保留第一个元素。