美文网首页
210816:查看class编译版本-List集合去重-将一个表

210816:查看class编译版本-List集合去重-将一个表

作者: 弹钢琴的崽崽 | 来源:发表于2021-08-16 22:25 被阅读0次

    一. 查看class编译版本

    1. javap命令

    javap 命令行工具是用作反编译的,在反编译信息中,可以看到编译的版本信息。

    其中 major version 就是编译的版本号,这里的 52 代表 JDK1.8。

    编译版本与 JDK 版本对照表

    JDK 版本号 Class 版本号 16 进制
    1.1 45.0 00 00 00 2D
    1.2 46.0 00 00 00 2E
    1.3 47.0 00 00 00 2F
    1.4 48.0 00 00 00 30
    1.5 49.0 00 00 00 31
    1.6 50.0 00 00 00 32
    1.7 51.0 00 00 00 33
    1.8 52.0 00 00 00 34

    2. Linux中hexdump命令

    hexdump主要用来查看“二进制”文件的十六进制编码。注意:它能够查看任何文件,不限于与二进制文件。

    二. List集合去重方法

    为了在下文中进行测试内容讲解,我们先做一些初始化数据

    public class ListRmDuplicate {
      private List<String> list;
      private List<Player> playerList;
    
      @BeforeEach
      public void setup() {
        list  =  new ArrayList<>();
        list.add("kobe");
        list.add("james");
        list.add("curry");
        list.add("zimug");
        list.add("zimug");
    
        playerList= new ArrayList<>();
        playerList.add(new Player("kobe","10000"));  //科比万岁
        playerList.add(new Player("james","32"));
        playerList.add(new Player("curry","30"));
        playerList.add(new Player("zimug","27"));   // 注意这里名字重复
        playerList.add(new Player("zimug","18"));   //注意这里名字和年龄重复
        playerList.add(new Player("zimug","18")); //注意这里名字和年龄重复
    
      }
    }
    

    1. 集合元素整体去重

    下文中四种方法对List中的String类型以集合元素对象为单位整体去重。如果你的List放入的是Object对象,需要你去实现对象的equals和hashCode方法,去重的代码实现方法和List<String>去重是一样的。

    1.1 放入Set集合

    是大家最容易想到的,先把List数据放入Set,因为Set数据结构本身具有去重的功能,所以再将SET转为List之后就是去重之后的结果。这种方法在去重之后会改变原有的List元素顺序,因为HashSet本身是无序的,而TreeSet排序也不是List种元素的原有顺序。

    @Test
    void testRemove1()  {
      /*Set<String> set = new HashSet<>(list);
      List<String> newList = new ArrayList<>(set);*/
    
      //去重并排序的方法(如果是字符串,按字母表排序。如果是对象,按Comparable接口实现排序)
      //List<String> newList = new ArrayList<>(new TreeSet<>(list));
    
      //简写的方法
      List<String> newList = new ArrayList<>(new HashSet<>(list));
    
      System.out.println( "去重后的集合: " + newList);
    }
    

    控制台打印结果如下:

    去重后的集合: [kobe, james, zimug, curry]
    

    1.2 Stream流distinct去重

    使用就比较简单,先用stream方法将集合转换成流,然后distinct去重,最后在将Stream流collect收集为List。

    @Test
    void testRemove2()  {
      List<String> newList = list.stream().distinct().collect(Collectors.toList());
    
      System.out.println( "去重后的集合: " + newList);
    }
    

    控制台打印结果如下:

    去重后的集合: [kobe, james, curry, zimug]
    

    1.3 利用set.add(T)

    这种方法利用了set.add(T),如果T元素已经存在集合中,就返回false。利用这个方法进行是否重复的数据判断,如果不重复就放入一个新的newList中,这个newList就是最终的去重结果

    //三个集合类list、newList、set,能够保证顺序
    @Test
    void testRemove3()  {
    
      Set<String> set = new HashSet<>();
      List<String> newList = new  ArrayList<>();
      for (String str :list) {
        if(set.add(str)){ //重复的话返回false
          newList.add(str);
        }
      }
      System.out.println( "去重后的集合: " + newList);
    
    }
    

    控制台打印结果和第二种方法一致。

    1.4 newList.contains(T)方法

    这种方法已经脱离了使用Set集合进行去重的思维,而是使用newList.contains(T)方法,在向新的List添加数据的时候判断这个数据是否已经存在,如果存在就不添加,从而达到去重的效果。

    //优化 List、newList、set,能够保证顺序
    @Test
    void testRemove4() {
    
      List<String> newList = new  ArrayList<>();
      for (String cd:list) {
        if(!newList.contains(cd)){  //主动判断是否包含重复元素
          newList.add(cd);
        }
      }
      System.out.println( "去重后的集合: " + newList);
    
    }
    

    控制台打印结果和第二种方法一致。

    2. 按照集合元素对象属性去重

    其实在实际的工作中,按照集合元素对象整体去重的应用的还比较少,更多的是要求我们按照元素对象的某些属性进行去重。 看到这里请大家回头去看一下上文中,构造的初始化数据playerList,特别注意其中的一些重复元素,以及成员变量重复。

    2.1 TreeSet实现Comparator接口

    为TreeSet实现Comparator接口,如果我们希望按照Player的name属性进行去重,就去在Comparator接口中比较name。下文中写了两种实现Comparator接口方法:

    • lambda表达式:(o1, o2) -> o1.getName().compareTo(o2.getName())
    • 方法引用:Comparator.comparing(Player::getName)
    @Test
    void testRemove5() {
      //Set<Player> playerSet = new TreeSet<>((o1, o2) -> o1.getName().compareTo(o2.getName()));
      Set<Player> playerSet = new TreeSet<>(Comparator.comparing(Player::getName));
      playerSet.addAll(playerList);
    
      /*new ArrayList<>(playerSet).forEach(player->{
        System.out.println(player.toString());
      });*/
      //将去重之后的结果打印出来
      new ArrayList<>(playerSet).forEach(System.out::println);
    }
    

    输出结果如下:三个zimug因为name重复,另外两个被去重。但是因为使用到了TreeSet,list中元素被重新排序。

    Player{name='curry', age='30'}
    Player{name='james', age='32'}
    Player{name='kobe', age='10000'}
    Player{name='zimug', age='27'}
    

    2.2 使用Predicate

    Predicate(有人管这个叫断言,从英文的角度作为名词可以翻译为谓词,作为动词可以翻译为断言)。谓词就是用来修饰主语的,比如:喜欢唱歌的小鸟,喜欢唱歌就是谓词,用来限定主语的范围。所以我们这里是用来filter过滤的,也是用来限制主语范围的,所以我认为翻译为谓词更合适。随便吧,看你怎么觉得怎么理解合理、好记,你就怎么来。

    • 首先我们定义一个谓词Predicate用来过滤,过滤的条件是distinctByKey。谓词返回ture元素保留,返回false元素被过滤掉。
    • 当然我们的需求是过滤掉重复元素。我们去重逻辑是通过map的putIfAbsent实现的。putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。
    • 如果putIfAbsent返回null表示添加数据成功(不重复),如果putIfAbsent返回value(value==null :false),则满足了distinctByKey谓词的条件元素被过滤掉。

    这种方法虽然看上去代码量增大了,但是distinctByKey谓词方法只需要被定义一次,就可以无限复用。

    @Test
    void testRemove7() {
      List<Player> newList = new ArrayList<>();
      playerList.stream().filter(distinctByKey(p -> p.getName()))  //filter保留true的值
              .forEach(newList::add);
    
      newList.forEach(System.out::println);
    }
    
    static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
      Map<Object,Boolean> seen = new ConcurrentHashMap<>();
      //putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。
      //如果返回null表示添加数据成功(不重复),不重复(null==null :TRUE)
      return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
    

    输出结果如下:三个zimug因为name重复,另外两个被去重。并且没有打乱List的原始顺序

    Player{name='kobe', age='10000'}
    Player{name='james', age='32'}
    Player{name='curry', age='30'}
    Player{name='zimug', age='27'}
    

    2.3 对某几个元素去重(改造上面的方法)

    上面的例子都是按某一个对象属性进行去重,如果我们想按照某几个元素进行去重,就需要对上面的三种方法进行改造。 我只改造其中一个,另外几个改造的原理是一样的,就是把多个比较属性加起来,作为一个String属性进行比较。

    @Test
    void testRemove8() {
      Set<Player> playerSet = new TreeSet<>(Comparator.comparing(o -> (o.getName() + "" + o.getAge())));
    
      playerSet.addAll(playerList);
    
      new ArrayList<>(playerSet).forEach(System.out::println);
    }
    

    三. 将一个表的某个字段值赋给另一个

    update T_SLXF_APP_MENU_CONFIG t1 set t1.MERGE_LM_ID = (select t2.ID from T_SLXF_APP_MENU_CONFIG t2 where t2.id = t1.id);
    

    四. 查看git项目是哪个分支的

    1. 查看项目git服务器地址

    输入git remote -v

    即可查看git的服务器地址:

    2. 查看是从哪个分支上拉的代码

    git remote show origin
    

    相关文章

      网友评论

          本文标题:210816:查看class编译版本-List集合去重-将一个表

          本文链接:https://www.haomeiwen.com/subject/izwvbltx.html