The pit used by the Lists.transform method - a summary of the pits 16 (updated once a week)

Continue to create, accelerate growth! This is the sixth day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the details of the event

background

The Lists.transform method provided by google can be used to transform a List of an entity class into a List of another entity class through certain logic. For example, the following example converts a list of strings to a list of integers.

For example: List<String>A is converted to List<Integer>B. As shown

public static void main(String[] args) {
    List<String> tests = Stream.of("haha", "hehe").collect(Collectors.toList());
    List<Integer> integers = Lists.transform(tests, t -> {
        return t;
    });
}
复制代码

question

The collection ids adds a value in the Lists.transform method, but it is not added in the end.

public static void main(String[] args) {
    List<Long> ids=new ArrayList<>();
    List<Integer> tests = Stream.of("123", "321").collect(Collectors.toList());
    List<Integer> integers = Lists.transform(tests, t -> {
        ids.add(1L);
        return Integer.parseInt(t);
     });
    System.out.println("结果:"+JSON.toJSON(ids));
}
复制代码

The print result is as follows:

image.png

Let's hit a breakpoint to see if it executes

You can see that the first breakpoint did not go in, and the second breakpoint went directly.image.png

reason

From the above phenomenon, it can be seen that

  • The Lists.transform method does not actually do the transformation immediately, but delays the transformation.
  • Querying the source code shows that our sourceList is not assigned a value immediately after executing Lists.transform, it is just converted to TransformingRandomAccessList type, which rewrites the iterator, every time we iterate userFormList, it will be The function will be called for assignment.
  • And every time the function passed in foreach will be executed once, the method in the function needs to be more efficient. Therefore, if used improperly, there will be problems. The principle is a bit like sublist, it actually returns an inner class.

image.png

image.png

Solution

The first way: use a wrapper class to wrap the returned inner object

  public static void main(String[] args) {
        List<Long> ids = new ArrayList<>();
        List<String> tests = Stream.of("123", "321").collect(Collectors.toList());
//        List<Integer> integers = Lists.transform(tests, t -> {
//            ids.add(1L);
//            return Integer.parseInt(t);
//        });
        List<Integer> integers = new ArrayList<>(Lists.transform(tests, t -> {
            ids.add(1L);
            return Integer.parseInt(t);
        }));

        System.out.println("结果:" + JSON.toJSON(ids));
    }
复制代码

Results of the:

image.png

The second way: implement a simple transform without the method provided by google

public static <F, T> List<T> transformList(List<F> fromList, Function<F, T> fuction) {
    if (fromList == null) {
        return new ArrayList<>();
    }
    List<T> lists = new ArrayList<>();
    for (F from : fromList) {
        lists.add(fuction.apply(from));
    }
    return lists;
}
复制代码

Write a main method to test usage:

  public static void main(String[] args) {
        List<Long> ids = new ArrayList<>();
        List<String> tests = Stream.of("123", "321").collect(Collectors.toList());
//        List<Integer> integers = Lists.transform(tests, t -> {
//            ids.add(1L);
//            return Integer.parseInt(t);
//        });
//        List<Integer> integers = new ArrayList<>(Lists.transform(tests, t -> {
//            ids.add(1L);
//            return Integer.parseInt(t);
//        }));
        List<Tet2> tet2List=new ArrayList<>();
        Tet2 tet2=new Tet2(1L,"haha");
        tet2List.add(tet2);
        List<Tet1> tet1List = transformList(tet2List, m -> {
            Tet1 tet1 = new Tet1();
            tet1.setId(m.getId());
            tet1.setName(m.getName());
            return tet1;
        });
        System.out.println("结果:" + JSON.toJSON(tet1List));
    }
复制代码

The print result is as follows:

image.png

Summarize

When using a third-party open source framework, be sure to understand its principles to prevent hidden pits in the use of third-party frameworks.

Guess you like

Origin juejin.im/post/7105581965503365127