0
 @Transactional(isolation = Isolation.READ_UNCOMMITTED
            , propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void insertPhoneAndArea(List<RecordEntity> recordEntityList) {
        int tryCount = 0;
        OffsetTime startTime = OffsetTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        Map<String, List<RecordEntity>> selfGroup = recordEntityList.stream().collect(Collectors.groupingBy(RecordEntity::getSelfNum));
        while (0==selfGroup.size()) {
            //There has a bug with Jdk Stream to groupBy in One elements ,So have a loop try
            selfGroup = recordEntityList.stream().collect(Collectors.groupingBy(RecordEntity::getSelfNum));
            tryCount++;
            if (tryCount > 20000) {
                break;
            }
            log.info("try to get SelfNum with Stream bug ! count in {} ",tryCount);
        }
}

Steps:

  1. Invoking the method with name insertPhoneAndArea
  2. Given the same data with variables, with "recordEntityList" in there, and it was not empty
  3. When I executed the method, the selfGroup was empty and it's size was zero. So I feel strange with the result. It shouldn't be empty because the recordEntityList was not empty.
  4. I turned on the Debug Mode with IDEA and I was using Alt+LeftClick to execute the code and the result was correct, it wasn't empty.
  5. So I wrote a try count in the group code, as expected, that code in the loop was approximately random up to 30, and it was a correct result and it was out of the while loop.

I don't know what the bug is.

@Data
public class RecordEntity {

    private int id;
    /**
     * 通话时间
     */
    private Date recordTime;
    /**
     * 持续时长
     */
    private Integer duration;
    /**
     * 通话方式/ 1电话主叫、2电话被叫、3短信主叫、4短信被叫
     */
    private Integer recordMode;
    /**
     * 对方电话号码
     */
    private String dialNum;
    /**
     * 通话地点
     */
    private String recordAddress;
    /**
     * 通话类型/ 1本地、2异地
     */
    private Integer recordType;
    /**
     * 小区编号
     */
    private String area;
    /**
     * 基站号
     */
    private String baseStation;
    /**
     * 交换机号
     */
    private String exchange;
    /**
     * 本机号码
     */
    private String selfNum;
    /**
     * 机主姓名
     */
    private String username;
    /**
     * 机主身份证
     */
    private String idNum;
    /**
     * 通话记录id(唯一)
     */
    private String recordId;
    /**
     * 话单运营商
     */
    private Integer operator;
    /**
     * 对方号码类型(1-手机,2-固话,3-服务号)
     */
    private Integer dialNumType;
}
Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
Allen
  • 88
  • 6
  • 1
    Please [edit] your question and add the definition of `RecordEntity`, especially the `getSelfNum` method. If it returns a non-standard type, the definition of that type as well, and everything they depend on (fields, the methods that fill the fields, etc.). In short, create a [mcve]. – RealSkeptic Jan 15 '20 at 09:08
  • 1
    What type does `recordEntityList` have? Any chance for concurrent modifications? – Holger Jan 16 '20 at 18:37
  • @Holger Do you think that concurrent modifications might account for 20 000 times getting an empty map from a non-empty list? – Ole V.V. Jan 16 '20 at 20:16
  • 1
    @OleV.V. it can account for any number of times. Currently, we don’t even know the direction the concurrent change, if there is one, (empty → non empty, or non empty → empty, or just producing an inconsistent state). I’m also thinking into [this direction](https://stackoverflow.com/a/37926832/2711488), which would explain why every inspection of the list makes the problem go away. – Holger Jan 17 '20 at 08:48

2 Answers2

2

If Map<String, List<RecordEntity>> selfGroup = recordEntityList.stream().collect(Collectors.groupingBy(RecordEntity::getSelfNum)); sets selfGroup to an empty map, it must be because recordEntityList is empty.

Why the caller is passing an empty list to your method I obviously cannot tell.

PS You don’t need the Yoda condition, 0==selfGroup.size(). I’d recommend selfGroup.isEmpty().

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thanks for your recommendation, but the caller is not provide an empty list to the method when the bug did. – Allen Jan 16 '20 at 02:30
  • Thanks for reporting back. I wouldn’t be too sure. In any case, if we’re to investigate further, we will need you to [create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Ole V.V. Jan 16 '20 at 05:07
0

any chance that selfNum is null? you can't group by null, actually, you'll get an exception. if not, try using phrase in another locale.

  • You are correct about the latter: if `getSelfNum()` returns `null`, you will get `java.lang.NullPointerException: element cannot be mapped to a null key`. This clearly doesn’t happen in the code in the question since it is repeated 20000 times. – Ole V.V. Jan 15 '20 at 09:59
  • Thanks for your answer, the method caller does not gaving empty list and that's selfNum never has null, when the method executes the method that has an empty selfGroup,but the result correct in the loop about try eg: 16 counts to out the loop. – Allen Jan 16 '20 at 02:36