Comparator 接口使用方法,结合java8新特性及源码分析

news2024/11/26 2:47:49

目录

  • 1 Comparator介绍
    • 1.1 函数式声明
    • 1.2 简单的小案例
  • 2. Comparator中的方法
    • 2.1 compare 抽象方法
      • 例子
    • 2.2 comparing方法
      • 源码
        • 参考解释
        • 详细解释
      • <? super T, ? extends U>讲解
      • comparing代码样例
      • 例子comparing中的方法源码分析
      • <T, U extends Comparable<? super U>> 讲解
        • 超类型是什么意思?
      • 泛型增强灵活性性例子
        • 方法的类型参数例子
      • sorted 源码分析

1 Comparator介绍

建议看英文文档

官方英文文档介绍
https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/Comparator.html

Comparator是一个函数式接口,因此可以用作 lambda 表达式或方法引用的赋值目标。它经常用于没有天然排序的集合进行排序,如 Collections.sort 或 Arrays.sort。或者对于某些有序数据结构的排序规则进行声明,如 TreeSet 、TreeMap 。也就是该接口主要用来进行集合排序。
在这里插入图片描述

1.1 函数式声明

函数式声明(Functional Declaration) 是指在Java中使用函数式编程的方式声明函数或方法。函数式编程是一种编程范式,它将计算视为函数应用的方式,强调了函数的纯粹性和不可变性。在Java中,函数式编程通常使用Lambda表达式、方法引用、函数接口等特性来实现。在你提供的代码中,Lambda表达式 (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2)) 就是一个函数式声明,它表示一个比较器的定义,将对象的比较规则抽象为一个函数。

总之,comparing 方法是一个函数式编程的示例,它接受函数和比较器作为参数,然后返回一个基于提取的键值和键比较器的比较器,用于对象的排序。这种方式使得你可以轻松地基于对象的属性进行比较,而无需编写大量的比较逻辑。

1.2 简单的小案例

List<People> peoples = new ArrayList<>();
  // 中间省略
  // 按照年龄从小到大排序
peoples.sort(Comparator.comparing(People::getAge));

2. Comparator中的方法

Comparator 作为一个函数式接口只有一个抽象方法,但是它有很多的默认方法,我们来认识一下这些方法们。

2.1 compare 抽象方法

作为Comparator 唯一的抽象方法,int compare(T o1,T o2) 比较两个参数的大小, 返回负整数,零,正整数 ,分别代表 o1<o2、o1=o2、o1>o2,通常分别返回 -1、0 或 1。伪表达式:

// 输入两个同类型的对象 ,输出一个比较结果的int数字
(x1,x2)-> int

例子

自己动动手

public class SortedDemo {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("watermelon","apple", "banana", "cherry");

        // 使用比较器按字符串长度升序排序
        words.sort((str2, str1) -> Integer.compare(str1.length(), str2.length()));

        // words.sort((str2, str1) -> Integer.compare(str1.length(), str2.length()));//降序

        System.out.println(words); // 输出: [apple, banana, cherry]

    }
}

2.2 comparing方法

Java 8 开始,Comparator 提供了一系列的静态方法,并通过函数式的风格赋予 Comparator 更加强大和方便的功能,我们暂且称它们为 comparing系列方法。

重点介绍一下
comparing方法,以及它的源码实现。注意comparing方法有很多个不同的重载方法,这个是传入参数最全的方法介绍。

源码

   public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

参考解释

该方法是该系列方法的基本方法。是不是看上去很难懂的样子?我们来分析一下该方法。它一共两个参数都是函数式接口。

第一个参数 Function<? super T, ? extends U> keyExtractor 表示输入一个是 T 类型对象,输出一个 U 类型的对象,举个例子,输入一个 People 对象返回其年龄 Integer 数值:

//   people -> people.getAge(); 转换为下面方法引用
Function<People, Integer> getAge = People::getAge;

第二个参数 keyComparator就很好理解了,表示使用的比较规则。

c1,c2 按照 第一个参数 keyExtractor 提供的规则进行提取特征,然后第二个参数keyComparator对这两个特征进行比较。下面的式子其实可以概括为 3.1 的 (x1,x2)-> int

(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2))

Comparator & Serializable 为 Java 8 新特性:同时满足这两个类型约束

理解了这个方法后,其它该系列的方法就好理解了,这里不再赘述。目前 comparing 系列方法使用更加广泛。我们举一些例子:

List<People> peoples = new ArrayList<>();
//  ………………
// 按照年龄从低到高排序
peoples.sort(Comparator.comparing(People::getAge));
// 按照年龄从高到低排序
peoples.sort(Comparator.comparing(People::getAge, (x, y) -> -x.compareTo(y)));

同样你可以使用 java.util.Collections 或者 Stream 提供的排序方法来使用Comparator。

详细解释

这段源码是Java标准库中的一个方法,位于java.util.Comparator类中,它是一个静态方法,用于创建一个比较器(Comparator),该比较器基于给定的函数(Function)和键比较器(Comparator)来比较对象。

现在让我逐步解释这段源码:

  1. <T, U>:这是泛型方法的定义,它表明这个方法具有两个泛型类型参数 TU,用于表示要比较的元素类型和提取关键值的类型。

  2. comparing 方法接受两个参数:

    • keyExtractor 参数是一个函数,它接受类型为 T 的对象,并返回类型为 U 的键值。这个函数用于从对象中提取比较的关键值。
    • keyComparator 参数是一个比较器,它用于比较类型为 U 的键值。
  3. Objects.requireNonNull(keyExtractor)Objects.requireNonNull(keyComparator):这两行代码用于检查传入的 keyExtractorkeyComparator 参数是否为 null,如果是 null,则抛出 NullPointerException

  4. 返回值:该方法的返回值是一个比较器(Comparator<T>)。这个比较器基于传入的 keyExtractor 函数和 keyComparator 比较器来进行对象比较。

    (Comparator<T> & Serializable)
    (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2))
    
    • (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2)):这是一个Lambda表达式,表示一个比较器的具体实现。它接受两个对象 c1c2,首先使用 keyExtractor 函数从这两个对象中提取键值,然后使用 keyComparator 比较这两个键值,返回比较结果。这就实现了一个基于键值的对象比较器。
    • (Comparator<T> & Serializable):这是一个类型转换,将Lambda表达式转换为 Comparator<T> 类型,并且标记为 Serializable,以便可以序列化该比较器。

这个方法的主要目的是创建一个比较器,该比较器可以基于提取的键值和键比较器来对对象进行排序。这种方式使得排序可以更加灵活,可以根据对象的某个属性进行比较,而不是直接比较对象本身。

<? super T, ? extends U>讲解

<? super T, ? extends U> 通配符(wildcard)

  • ? super T 表示通配符的下界(Lower Bounded Wildcard),它的意思是可以接受类型为 TT 的超类型的对象。这允许传递比 T 更一般的对象类型作为参数。例如,如果 TNumber,那么 ? super T 可以接受 NumberObject 或其他 Number 的超类型作为参数。

  • ? extends U 表示通配符的上界(Upper Bounded Wildcard),它的意思是可以接受类型为 UU 的子类型的对象。这允许传递比 U 更具体的对象类型作为参数。例如,如果 UInteger,那么 ? extends U 可以接受 IntegerNumber 或其他 Integer 的子类型作为参数。

comparing 方法的源码中,keyExtractorkeyComparator 的类型使用了通配符的形式,是为了增加方法的灵活性。它们的类型参数分别为 <? super T, ? extends U>,其中 T 表示比较器的元素类型,U 表示要比较的键值类型。使用通配符可以让 comparing 方法接受更广泛的类型参数,从而更灵活地适应不同的使用情况。

comparing代码样例

comparing

package com.qfedu.Comparator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 *     public static <T, U> Comparator<T> comparing(
 *             Function<? super T, ? extends U> keyExtractor,
 *             Comparator<? super U> keyComparator)
 *     {
 *         Objects.requireNonNull(keyExtractor);
 *         Objects.requireNonNull(keyComparator);
 *         return (Comparator<T> & Serializable)
 *                 (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
 *                         keyExtractor.apply(c2));
 *     }
 */

public class ComparatorDemo {
    public static void main(String[] args) {
        // 创建一个包含Person对象的列表
        List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 35)
        );

        // 使用comparing方法按年龄升序排序Person对象
        Comparator<Person> ageComparator = Comparator.comparing(
                person -> person.getAge() // 提取比较的键值:年龄
        );

        // 对列表进行排序
        List<Person> sortedPeople = people.stream()
                .sorted(ageComparator)
                .collect(Collectors.toList());

        // 输出排序后的结果
        sortedPeople.forEach(person -> System.out.println(person.getName() + ": " + person.getAge()));
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

注释解释:

  1. 我们创建了一个 Person 类,表示一个人,包括姓名和年龄属性。

  2. main 方法中,我们创建了一个包含 Person 对象的列表 people

  3. 使用 Comparator.comparing 方法创建了一个比较器 ageComparator,该比较器按照 Person 对象的年龄进行比较。这里的 person -> person.getAge() 是一个键提取函数,用于提取年龄作为比较的键值。

  4. 我们使用 sorted 方法将 people 列表按照 ageComparator 进行排序,得到排序后的列表 sortedPeople

  5. 最后,我们遍历 sortedPeople 列表,并输出排序后的结果,按照年龄升序排列。

这个示例演示了如何使用 comparing 方法创建一个比较器,以及如何基于键值对对象进行排序。通配符 <? super T, ? extends U> 使得 comparing 方法可以适应不同类型的对象和键值。在本例中,键值是年龄,对象是 Person

例子comparing中的方法源码分析

例子中的comparing方法只有传入一个函数参数Function<? super T, ? extends U>,方法的声明<T, U extends Comparable<? super U>>表示:

  • 方法或类接受两个泛型类型参数 TU
  • U 必须是一个实现了 Comparable 接口的类型,但可以是 Comparable 接口的任何超类型。
// 使用comparing方法按年龄升序排序Person对象
        Comparator<Person> ageComparator = Comparator.comparing(
                person -> person.getAge() // 提取比较的键值:年龄
        );
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor)
{
    Objects.requireNonNull(keyExtractor);
    return (Comparator<T> & Serializable)
        (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

<T, U extends Comparable<? super U>> 讲解

这个代码片段 <T, U extends Comparable<? super U>> 是Java泛型的类型参数声明,它包含两个泛型类型参数 TU,并对泛型类型 U 进行了限定。

让我逐步解释这个代码片段的含义:

  1. <T, U>:这部分表示声明两个泛型类型参数 TU,它们是在方法或类中使用的类型占位符。T 通常表示某种对象的类型,而 U 表示另一种类型,用于在比较中作为键值。

  2. U extends Comparable<? super U>:这部分对泛型类型 U 进行了限定。它表示 U 必须是一个实现了 Comparable 接口的类型。Comparable 接口是Java中用于比较对象的接口,它定义了 compareTo 方法,允许对象自定义比较逻辑。

    • Comparable<U> 表示 U 必须直接实现 Comparable 接口,但我们使用 <? super U> 来更加灵活地定义 U<? super U> 表示 U 可以是 Comparable 接口的任何超类型。这允许我们比较对象 U 的时候,也可以比较它的子类或父类对象。

综合起来,<T, U extends Comparable<? super U>> 这个声明表示:

  • 方法或类接受两个泛型类型参数 TU
  • U 必须是一个实现了 Comparable 接口的类型,但可以是 Comparable 接口的任何超类型

这种声明的目的是使得方法或类更加通用和灵活,可以适应不同类型的对象,并且可以进行比较操作,而不仅限于特定的类型。这在编写通用的排序或比较逻辑时非常有用。

超类型是什么意思?

在Java中,一个类或接口可以实现另一个类或接口,而被实现的类或接口称为超类型(super type)。超类型是一个广义的概念,用于表示一个类或接口是另一个类或接口的父类或父接口。

当我们说 “U 可以是 Comparable 接口的任何超类型” 时,意思是泛型类型参数 U 可以是实现了 Comparable 接口的类或接口,而不仅仅限于直接实现 Comparable 接口的类。

这是非常有用的,因为它使得方法更加灵活,允许接受不仅仅是实现 Comparable 接口的类的对象,还可以接受那些实现了 Comparable 接口的类的子类的对象。这是因为子类也可以被视为超类型的一种,因为它们继承了超类型的行为。

举个例子,假设有一个 Fruit 类实现了 Comparable 接口,然后有一个 Apple 类,它是 Fruit 的子类。如果我们有一个方法要接受一个实现了 Comparable 接口的对象,那么这个方法的声明可以这样写:

public <U extends Comparable<? super U>> void someMethod(U obj) {
    // 方法体
}

在这个方法中,U 表示可以是 Comparable 接口的任何超类型,因此可以接受 FruitApple 对象作为参数,因为它们都实现了 Comparable 接口。这样,方法变得更加通用,可以接受不同类型的对象,只要它们实现了 Comparable 接口或其超类型。

泛型增强灵活性性例子

我不太能感受到它的通用和灵活,能用一个代码例子说明吗,最好有对比

当我们定义泛型方法或类时,我们希望它们能够处理各种类型的数据,而不仅仅是特定类型。通过使用 extends Comparable<? super U> 这样的泛型类型参数限定,我们可以实现通用的比较方法,使其可以适用于不同类型的对象。

下面,我将为你提供一个例子,演示如何使用泛型和 Comparable 来创建通用的比较方法。首先,我们将创建一个普通的比较方法,然后通过泛型和 extends Comparable<? super U> 来改进它,使其更加通用。

示例 1:普通的比较方法

public static int compareIntegers(int a, int b) {
    if (a < b) {
        return -1;
    } else if (a > b) {
        return 1;
    } else {
        return 0;
    }
}

public static void main(String[] args) {
    int result = compareIntegers(5, 3);
    System.out.println(result); // 输出 1
}

在这个示例中,compareIntegers 方法只能比较整数类型,并且返回整数类型的结果。

示例 2:使用泛型和 Comparable 的通用比较方法

public static <T extends Comparable<? super T>> int compareObjects(T a, T b) {
    return a.compareTo(b);
}

public static void main(String[] args) {
    int result1 = compareObjects(5, 3); // 使用整数比较
    System.out.println(result1); // 输出 1

    String str1 = "apple";
    String str2 = "banana";
    int result2 = compareObjects(str1, str2); // 使用字符串比较
    System.out.println(result2); // 输出 -1
}

在示例 2 中,我们定义了一个泛型方法 compareObjects,它接受两个泛型参数 T,这两个参数必须是实现了 Comparable 接口的类型,而且我们使用 extends Comparable<? super T> 来表明泛型类型 T 或其超类型必须实现 Comparable 接口。

这使得 compareObjects 方法能够比较不同类型的对象,而不仅仅是整数。我们可以使用它来比较整数和字符串,它会根据对象的 compareTo 方法来进行比较,产生通用的比较结果。

通过泛型和 Comparable,我们实现了一个通用的比较方法,可以用于比较不同类型的对象,这增加了方法的通用性和灵活性。这是泛型和类型参数限定的一个强大之处。

方法的类型参数例子

类型参数声明用于指定在方法或类中使用的泛型类型参数,以使方法或类更通用,可以适应不同类型的数据。以下是一些示例,演示了方法的类型参数声明:

  1. 简单的泛型方法

    public <T> T findMax(T[] arr) {
        T max = arr[0];
        for (T element : arr) {
            if (element.compareTo(max) > 0) {
                max = element;
            }
        }
        return max;
    }
    

    在这个示例中,<T> 表示这是一个泛型方法,它接受一个泛型数组 T[],并返回数组中的最大元素。T 是类型参数,可以是任何引用类型,例如整数、字符串、自定义对象等。

  2. 使用多个类型参数

    public <T, U> boolean areEqual(T obj1, U obj2) {
        return obj1.equals(obj2);
    }
    

    这个示例中有两个类型参数 <T, U>。方法接受两个参数,一个是类型为 T 的对象 obj1,另一个是类型为 U 的对象 obj2。该方法比较这两个对象是否相等。

  3. 泛型类的类型参数

    public class Box<T> {
        private T value;
        
        public Box(T value) {
            this.value = value;
        }
        
        public T getValue() {
            return value;
        }
    }
    

    这是一个泛型类 Box<T> 的例子。T 是类型参数,用于表示盒子中存储的值的类型。这个类可以用于存储不同类型的值。

  4. 泛型接口的类型参数

    public interface List<T> {
        void add(T item);
        T get(int index);
    }
    

    这是一个泛型接口 List<T> 的示例,表示一个通用的列表接口。T 是类型参数,表示列表中元素的类型。具体的列表实现可以指定 T 的具体类型。

这些示例展示了如何在方法和类中使用类型参数声明,以实现通用性和灵活性,以适应不同类型的数据。类型参数允许我们编写通用的代码,而不必在每次使用不同类型时都编写不同的方法或类。

sorted 源码分析

Stream<T> sorted(Comparator<? super T> comparator);

sorted 方法将使用传入的比较器来对 Stream 中的元素进行排序,然后生成一个新的 Stream,其中包含了按照比较器定义的顺序排列的元素。这个方法通常用于对集合中的元素进行排序操作

        // 使用comparing方法按年龄升序排序Person对象
        Comparator<Person> ageComparator = Comparator.comparing(
            person -> person.getAge() // 提取比较的键值:年龄
        );
        //sort(Comparator.comparing(People::getAge)); 也可以这么写
		// 对列表进行排序
        List<Person> sortedPeople = people.stream()
                .sorted(ageComparator)
                .collect(Collectors.toList());

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1020228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python asynchat模块-异步套接字处理-服务器程序示例

介绍 此模块在asyncore架构上建立&#xff0c;简化了异步客户端和服务器&#xff0c;并且使得处理元素为任意字符串结束或者为变长度的协议更加容易。asynchat定义了一个可以由使用者来子类化的抽象类async_chat&#xff0c;提供了collect_incoming_data()和found_terminator(…

数据结构上机练习——单链表的基本操作、头文件、类定义、main函数、多种链表算法的实现,含注释

文章目录 单链表的基本操作实现1.头文件2.类定义和多种算法的实现2.1创建空表2.2头插法创建n个元素的线性链表2.3一个带头节点的链表存放一组整数&#xff0c;设计一个算法删除值等于x的所有节点。2.4计算线性表中值为偶数的节点个数2.5一个带头节点的单链表heada存放一组整数&…

科技云报道:云安全的新战场上,如何打破“云威胁”的阴霾?

科技云报道原创。 近年来&#xff0c;在云计算和网络安全产业的蓬勃发展下&#xff0c;我国云安全行业市场规模呈现高速增长态势&#xff0c;在网络安全市场总体规模中占比不断上升。 据统计&#xff0c;近5年我国云安全市场保持高速增长&#xff0c;2021年我国云安全市场规模…

VMware workstation 中centos7虚拟机在nat模式下怎么配置网卡,指定我想要的IP并且可以联网

1、首先打开我们的虚拟网络编辑器 2、查看我们的网关 3、查看IP池&#xff0c;根据需求自己设置 4、打开centos7虚拟机 编辑网卡配置 vim /etc/sysconfig/network-scripts/ifcfg-ens160####我的网卡是ens160TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic …

全新交友平台,探索在线交流的乐趣!

大家好&#xff01;今天给大家介绍一款全新的交友平台&#xff0c;让您轻松享受在线交流的乐趣&#xff01;这个平台以其丰富多样的功能和互动体验而广受欢迎。无论您是想结识新朋友还是找到心仪的主播&#xff0c;这里都能满足您的需求。 首先&#xff0c;我们来看一下首页列表…

基于SpringBoot的超市管理系统

基于SpringBootVue的超市管理系统、超市进销存系统&#xff0c;前后端分离 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色&#xff1a;管理员…

三、C#—变量,表达式,运算符(1)

&#x1f33b;&#x1f33b; 目录 一、变量1.1 变量1.2 使用变量的步骤1.3 变量的声明1.4 变量的命名规则1.5 变量的初始化1.6 变量初始化的三种方法1.7 变量的作用域1.8 变量使用实例1.9 变量常见错误 二、C#数据类型2.1 数据类型2.2 值类型2.2.1 值类型直接存储值2.2.2 简单类…

Vivado初体验LED工程

文章目录 前言一、PL 和 PS二、LED 硬件介绍三、创建 Vivado 工程四、创建 Verilog HDL 文件五、添加管脚约束六、添加时序约束七、生成 BIT 文件八、仿真测试九、下载测试 前言 本节我们要做的是熟练使用 Vivado 创建工程并实现对 LED 灯控制&#xff0c;每秒钟控制开发板上的…

微信小程序手写时间间隔组件,可设置间隔时间一分钟,半小时,一小时的间隔

纯手写时间间隔组件 需求&#xff1a;小程序中可以根据时间段进行选择开始时间和结束时间&#xff0c;如&#xff1a;当前时间是09&#xff1a;00&#xff0c; 则我可以从9点开始选择时间&#xff0c;每半个小时为间隔&#xff0c;那么下一个时间就算9&#xff1a;30&#xff…

vue基础知识十三:Vue中的$nextTick有什么作用?

一、NextTick是什么 官方对其的定义 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的 DOM 什么意思呢&#xff1f; 我们可以理解成&#xff0c;Vue 在更新 DOM 时是异步执行的。当数据发生变化&#xff0c;Vue将开启一个异…

阿里测试岗:惨不忍睹的三面,幸好做足了准备,月薪17k,已拿offer....

我今年25岁&#xff0c;专业是电子信息工程本科&#xff0c;19年年末的时候去面试&#xff0c;统一投了测试的岗位&#xff0c;软件硬件都有&#xff0c;那时候面试的两家公司都是做培训的&#xff0c;当初没啥钱&#xff0c;他们以面试为谎言再推荐去培训这点让我特别难受。 …

开启编程之门

自我介绍 目前已经大二了&#xff0c;计算机专业在读&#xff0c;是一个热爱编程&#xff0c;做事踏实专注的人。转眼间一年已经过去了&#xff0c;也接触编程一年了&#xff0c;但开始并没有对所学所想进行很好的总结和输出&#xff0c;这一年也有了新的很多感悟与心得&#x…

JVM——5.类文件结构

这篇文章我们来讲一下jvm的类文件结构 目录 1.引言 2.类文件结构概论 3.魔数与class文件的版本 4.常量池 5.访问标志 6.类索引、父类索引与接口索引集合 7.字段表集合 8.方法表集合 9.属性表集合 9.1code属性 9.2 Exception属性 10小结 1.引言 代码编译的结果从本…

vue学习-02vue入门之组件

删除Vue-cli预设 在用户根目录下(C:\Users\你的用户名)这个地址里有一个.vuerc 文件,修改或删除配置 组件 Props(组件之间的数据传递) Prop 的大小写 (camelCase vs kebab-case)不敏感Prop 类型: String Number Boolean Array Object Date Function Symbol传递静态或动态 Pr…

「聊设计模式」之抽象工厂模式(Abstract Factory)

&#x1f3c6;本文收录于《聊设计模式》专栏&#xff0c;专门攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎持续关注&&收藏&&订阅&#xff01; 前言 在软件开发中&#xff0c;设计模式是一种被广泛使用的经验…

kudu 1.4.0 离线安装

1.准备rpm安装包 kudu-1.4.0: kudu的基础安装包 kudu-client0-1.4.0: kudu的c++客户端共享库 kudu-client-devel-1.4.0: kudu的c++客户端共享库sdk kudu-master-1.4.0: kudu master kudu-tserver-1.4.0: kudu tserver

任意输入一个整数m,若m不是素数,则对m进行质因数分解,并以质因数从小到大顺序排列的乘积形式输出

每个合数都可以写成几个质数&#xff08;也可称为素数&#xff09;相乘的形式 &#xff0c;这几个质数就都叫做这个合数的质因数。 #include <stdio.h> int isPrime(int num)// 判断一个数是否是素数 {if (num < 2) {return 0;}for (int i 2; i * i < num; i) {…

汽车电子 -- CAN总线波特率计算方法

上一篇文章介绍 PCAN View 安装与使用 的时候&#xff0c;留下了两个问题&#xff0c;CAN总线波特率该怎么计算&#xff1f; 下图里的这些 Prescaler、tseg1、tseg2、sync Jump Width是什么意思&#xff1f; CAN2.0协议中定义标称位速率为一理想的发送器在没有重新同步的情况…

2023年毫米波行业研究报告

第一章 行业概况 1.1 定义 毫米波是一种电磁波&#xff0c;其波长范围在1毫米至10毫米之间&#xff0c;频率介于30GHz至300GHz。与sub-6G (6GHz以下频段&#xff09;的5G系统相比&#xff0c;5G毫米波通信在带宽、时延和灵活弹性空口配置方面具有明显优势。这使其能够有效地满…

风车时间锁管理 - 构建IPA文件加锁+签名+管理一站式解决方案

时间锁管理&#xff1a;是一种用于控制对某些资源、功能或操作的访问权限的机制&#xff0c;它通过设定时间限制来限制对特定内容、系统或功能的访问或执行&#xff0c;以提高安全性和控制性&#xff0c;时间锁管理常见于以下场景&#xff1a; 1. 文件或文档的保密性&#xff…