揭秘字符串的奥秘:探索String类的深层含义与源码解读

news2024/11/16 5:44:24

文章目录

    • 一、导论
      • 1.1 引言:字符串在编程中的重要性
      • 1.2 目的:深入了解String类的内部机制
    • 二、String类的设计哲学
      • 2.1 设计原则:为什么String类如此重要?
      • 2.2 字符串池的概念与作用
    • 三、String类源码解析
      • 3.1 成员变量
      • 3.2 构造函数
      • 3.3 equals(): 判断两个对象是否相等
      • 3.4 charAt(): 获取指定位置的字符
      • 3.5 length(): 获取字符串长度
      • 3.6 concat(): 字符串连接
      • 3.7 substring(): 子串提取
      • 3.8 compareTo (): 字符串长度相等的比较
      • 3.9 hashCode():重写hashCode
      • 3.10 replace ():新值替换旧值
      • 3.11 trim():去除空格
      • 3.12 startsWith():前缀+后缀
    • 四、String类的内部实现机制
      • 4.1 字符串的存储方式:常量池、堆、栈
      • 4.2 字符串不可变性的实现细节
    • 五、性能优化与字符串操作技巧
      • 5.1 使用StringBuilder和StringBuffer提高字符串拼接效率
      • 5.2 字符串比较的最佳实践
    • 六、案例分析与实例演示
      • 6.1 实际代码示例:如何更好地使用String类
      • 6.2 常见陷阱与解决方案

一、导论

1.1 引言:字符串在编程中的重要性

字符串在编程中非常重要,因为它们是处理文本数据的基本单位。在几乎所有编程语言中,都有专门的字符串类型和相关的操作方法,这些方法使得处理文本变得更加方便和灵活。

字符串在编程中的重要性

  1. 文本处理: 字符串用于存储和处理文本数据。无论是读取文件、用户输入还是与外部系统通信,都需要使用字符串。
  2. 数据表示: 许多数据格式,如JSON、XML和HTML,都使用字符串来表示结构化的数据。在这些情况下,字符串是将数据进行序列化和反序列化的基础。
  3. 用户界面: 用户界面中的文本标签、按钮标签等通常都是字符串。程序需要能够操作和显示这些字符串以与用户进行交互。
  4. 搜索和匹配: 字符串操作是执行搜索、替换和匹配操作的基础。正则表达式是一种强大的工具,用于在字符串中进行复杂的模式匹配。
  5. 密码学和安全性: 字符串在密码学中的使用非常广泛。加密和哈希算法通常对字符串进行操作,以确保数据的安全性。
  6. 网络通信: 在网络通信中,数据通常以字符串的形式传输。这包括HTTP请求和响应、数据库查询和响应等。
  7. 程序逻辑: 在编程中,字符串也常常用于表示程序中的命令、条件和逻辑结构。例如,条件语句中的比较操作就涉及到字符串的比较。

总体而言,字符串在编程中是一个不可或缺的组成部分,广泛用于处理和表示各种类型的文本数据。

1.2 目的:深入了解String类的内部机制

在Java中,String类是不可变的,这意味着一旦字符串对象被创建,它的内容就不能被修改。

String类内部机制的重要信息:

  1. 不可变性(Immutability): String类的不可变性是通过将字符数组(char数组)声明为final并使用private final char value[]来实现的。这意味着一旦字符串被创建,它的内容不能被更改。
  2. 字符串池(String Pool): Java中的字符串池是一种特殊的存储区域,用于存储字符串常量。当你创建一个字符串时,JVM首先检查字符串池是否已经存在相同内容的字符串,如果存在则返回池中的引用,否则创建一个新的字符串对象并放入池中。
  3. 常量池(Constant Pool): 字符串池实际上是常量池的一部分,其中存储了类、方法和接口中的常量数据。字符串常量池属于这个常量池。
  4. StringBuilder和StringBuffer: 在Java中,如果需要对字符串进行频繁的修改,建议使用StringBuilder(非线程安全)或StringBuffer(线程安全)而不是String。这是因为StringBuilderStringBuffer类提供了可变的字符串,避免了每次修改都创建新的字符串对象的开销。
  5. 字符串连接: 字符串连接使用+运算符时,实际上是创建了一个新的字符串对象。对于频繁的字符串连接操作,最好使用StringBuilderStringBuffer以提高性能。
  6. 字符串比较: 使用equals()方法来比较字符串的内容,而不是使用==运算符。equals()方法比较字符串的实际内容,而==运算符比较的是对象引用。
  7. 字符串不可变性的好处: 不可变字符串有助于线程安全,可以安全地在多个线程中共享,而无需担心数据被修改。此外,不可变性还有助于缓存字符串,提高性能。

总的来说,了解String类的内部机制有助于更有效地使用字符串,理解字符串的创建、比较和连接等操作的性能影响。

二、String类的设计哲学

2.1 设计原则:为什么String类如此重要?

String类之所以如此重要,主要是因为字符串在计算机编程中是一种非常常用的数据类型,而Java的String类提供了丰富的方法和功能,使得字符串的处理变得更加方便和灵活。

String类的重要特点和用途:

  1. 不可变性(Immutable): String类的实例是不可变的,一旦创建了字符串对象,就不能再修改它的值。这使得字符串在多线程环境下更安全,也更容易进行优化。

  2. 字符串连接和拼接: String类提供了丰富的方法来进行字符串的连接和拼接,例如使用+运算符或者concat()方法。这使得构建复杂的字符串变得简单,而且性能较好。

    String firstName = "John";
    String lastName = "Doe";
    String fullName = firstName + " " + lastName;
    
  3. 字符串比较: String类提供了用于比较字符串的方法,如equals()compareTo()。这些方法使得比较字符串内容变得方便,可以轻松地判断两个字符串是否相等。

    String str1 = "hello";
    String str2 = "world";
    if (str1.equals(str2)) {
        // 字符串内容相等
    }
    
  4. 字符串操作: String类包含许多有用的方法,如length()charAt()substring()等,可以对字符串进行各种操作,例如获取字符串长度、访问特定位置的字符、提取子串等。

    String text = "Hello, World!";
    int length = text.length(); // 获取字符串长度
    char firstChar = text.charAt(0); // 获取第一个字符
    String subString = text.substring(0, 5); // 提取子串
    
  5. 正则表达式: String类提供了支持正则表达式的方法,可以用于字符串的模式匹配和替换操作。

    String text = "The quick brown fox jumps over the lazy dog";
    String replacedText = text.replaceAll("fox", "cat");
    
  6. 国际化(Internationalization): String类提供了支持国际化的方法,可以处理不同语言和字符集的字符串。

String类的重要性在于它为字符串的处理提供了丰富的工具和方法,使得在Java中进行字符串操作变得更加方便、高效和安全。

2.2 字符串池的概念与作用

当谈到Java中的字符串池时,我们通常指的是字符串常量池,它是Java中用于存储字符串常量的一个特殊区域。

  1. 概念
    • 字符串池是一个位于堆区的特殊存储区域,用于存储字符串常量。
    • 字符串池是Java运行时数据区的一部分,它有助于提高字符串的重用性和节省内存。
  2. 作用
    • 字符串重用:字符串池确保相同内容的字符串在内存中只有一份。当你创建一个字符串常量时,Java首先检查字符串池中是否已经存在相同内容的字符串,如果存在,则返回池中的引用,而不是创建一个新的对象。
    • 节省内存:通过重用相同的字符串,避免了在内存中创建多个相同内容的字符串对象,从而节省了内存空间。
    • 提高性能:由于字符串常量池减少了相同字符串的创建和销毁,因此可以提高程序的性能。

下面是一个简单的例子,说明字符串池的工作方式:

String s1 = "Hello";  // 创建字符串常量 "Hello",存储在字符串池中
String s2 = "Hello";  // 直接引用字符串池中的 "Hello",不会创建新的对象

System.out.println(s1 == s2);  // 输出 true,因为它们引用的是相同的字符串对象

**解释:**由于字符串"Hello"在字符串池中已经存在,因此s2直接引用了已有的对象,而不是创建新的对象。这种字符串池的机制有助于提高内存利用率和程序性能。

三、String类源码解析

3.1 成员变量

在这里插入图片描述

3.2 构造函数

// 默认构造函数
public String() {
    // 通过空字符串的值("")来初始化新创建的字符串对象的值
    this.value = "".value;
}

// 带有 String 类型参数的构造函数
public String(String original) {
    // 将新创建的字符串对象的值设置为原始字符串对象的值
    // value 和 hash 是 String 对象的内部属性
    this.value = original.value; // 通过访问原始字符串对象的 value 属性来获取其值
    this.hash = original.hash; // 获取原始字符串对象的哈希码(hash code)
}

// 带有 char 数组参数的构造函数,使用 java.utils 包中的 Arrays 类进行复制
public String(char value[]) {
    // 使用 Arrays 类的 copyOf 方法复制传入的 char 数组
    // 将复制后的数组作为新字符串对象的值
    this.value = Arrays.copyOf(value, value.length);
}

// 用于根据给定的字符数组、偏移量和长度创建一个新的字符串对象
public String(char value[], int offset, int count) {
    // 检查偏移量是否小于零
    if (offset < 0) {
        // 表示字符串索引越界
       throw new StringIndexOutOfBoundsException(offset);
    }
    // 检查长度是否小于等于零
    if (count <= 0) {
        if (count < 0) {
            // 表示字符串索引越界
           throw new StringIndexOutOfBoundsException(count);
        }
        // 如果长度为零,并且偏移量在字符数组的范围内,则将新字符串的值设置为空字符串,然后返回
        // 为了处理特殊情况,以防止数组越界
        if (offset <= value.length) {
           this.value = "".value;
           return;
        }
    }
    // 检查偏移量和长度的组合是否超出了字符数组的范围
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        // 字符串索引越界
       throw new StringIndexOutOfBoundsException(offset + count);
    }
    // 如果通过了所有检查,使用Arrays.copyOfRange方法从输入字符数组中复制指定偏移量和长度的部分,然后将这个部分作为新字符串的值。
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}

// 接受一个字节数组 bytes,一个偏移量 offset,一个长度 length,以及一个字符集名称 charsetName
// 目的是将字节数组以指定的字符集解码成字符串
public String(byte bytes[], int offset, int length, String charsetName)
       throws UnsupportedEncodingException {
    // 参数表示要使用的字符集的名称,如果为 null,则抛出 NullPointerException 异常
   if (charsetName == null)
       throw new NullPointerException("charsetName");
    // 检查偏移量和长度是否在字节数组的有效范围内
   checkBounds(bytes, offset, length);
    // 用于实际的解码过程,将字节数组转换为字符串,并将结果存储在 this.value 字段中
   this.value = StringCoding.decode(charsetName, bytes, offset, length);
}

// 使用字节数组的全部内容,并将偏移量设置为0,长度设置为字节数组的长度。通过调用上一个构造方法来完成实际的字符串解码
public String(byte bytes[], String charsetName)
      throws UnsupportedEncodingException {
   this(bytes, 0, bytes.length, charsetName);
}

// 接受一个 StringBuffer 对象 buffer,并将其内容复制到新创建的 String 对象中
public String(StringBuffer buffer) {
    // 通过对 buffer 对象进行同步,确保在复制过程中没有其他线程对其进行修改
    synchronized(buffer) {
        // 使用 Arrays.copyOf 方法来复制字符数组,然后将结果存储在 this.value 字段中
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}

3.3 equals(): 判断两个对象是否相等

在这里插入图片描述

3.4 charAt(): 获取指定位置的字符

在这里插入图片描述

3.5 length(): 获取字符串长度

在这里插入图片描述

3.6 concat(): 字符串连接

在这里插入图片描述

3.7 substring(): 子串提取

在这里插入图片描述

3.8 compareTo (): 字符串长度相等的比较

在这里插入图片描述

3.9 hashCode():重写hashCode

在这里插入图片描述

3.10 replace ():新值替换旧值

在这里插入图片描述

3.11 trim():去除空格

在这里插入图片描述

3.12 startsWith():前缀+后缀

在这里插入图片描述

四、String类的内部实现机制

4.1 字符串的存储方式:常量池、堆、栈

在Java中,字符串可以存储在常量池(String Pool)、堆内存(Heap)和栈内存(Stack)中,具体取决于字符串的创建方式和使用情况。

  1. 常量池(String Pool):
    • 字符串池是常量池的一部分,用于存储字符串常量。
    • 当你使用字符串字面量创建一个字符串时,例如String str = "Hello";,字符串常量"Hello"会存储在常量池中。
    • 如果已经存在相同内容的字符串常量,那么新的字符串引用会指向已存在的字符串常量,而不会创建新的对象。
  2. 堆内存(Heap):
    • 当使用new关键字创建字符串对象时,例如String str = new String("Hello");,字符串对象会存储在堆内存中。
    • 不管字符串内容是否相同,每次使用new都会在堆内存中创建一个新的字符串对象,即使内容相同也会占用不同的内存空间。
  3. 栈内存(Stack):
    • 字符串引用变量(例如String str = ...;)本身存储在栈内存中,而不是字符串内容。
    • 如果一个方法内部创建了一个字符串对象,该引用变量也会存储在栈内存中。

下面是一个简单的示例,说明了字符串在常量池和堆中的存储方式:

String str1 = "Hello"; // 存储在常量池
String str2 = "Hello"; // 直接引用常量池中的"Hello"

String str3 = new String("Hello"); // 存储在堆内存
String str4 = new String("Hello"); // 存储在堆内存,不同于str3

System.out.println(str1 == str2); // true,因为引用的是同一个常量池中的对象
System.out.println(str3 == str4); // false,因为使用了new关键字,创建了两个不同的对象

请注意,对于字符串的比较,应该使用equals()方法而不是==运算符,因为==比较的是引用是否相同,而equals()比较的是字符串的内容是否相同。

4.2 字符串不可变性的实现细节

在Java中,字符串的不可变性是通过以下方式实现的:

  1. final修饰符: Java中的String类被声明为final,这意味着它不能被继承。因此,无法创建String类的子类来修改其行为。
  2. 字符数组: 字符串在Java内部是通过字符数组(char array)实现的。这个字符数组被声明为final,并且它的引用是私有的,因此外部无法直接访问。
  3. 不可变性方法: String类中的大多数方法都被设计为不会修改字符串本身,而是返回一个新的字符串。例如,concatsubstringreplace等方法都是返回新的字符串对象而不是修改原始字符串。
  4. StringBuilder和StringBuffer的区别: 如果需要对字符串进行频繁的修改,可以使用StringBuilder或者在多线程环境下使用StringBuffer。这两者与String不同,它们是可变的。StringBuilderStringBuffer允许修改其内部的字符序列,因此它们的性能可能更好。

虽然字符串是不可变的,但Java中的字符串池(String Pool)提供了一种机制,可以在一定程度上重用字符串对象,以提高性能和节省内存。字符串池可以通过String.intern()方法来使用。这个方法会在字符串池中查找相等的字符串,如果找到则返回池中的实例,否则将字符串添加到池中并返回。这种机制有助于减少内存占用,因为相同的字符串在池中只存在一份。

总的来说,Java中字符串的不可变性是通过final关键字、私有字符数组和返回新字符串的方法等多个机制来实现的。

五、性能优化与字符串操作技巧

5.1 使用StringBuilder和StringBuffer提高字符串拼接效率

在Java中,StringBuilderStringBuffer都是用于处理字符串拼接的类,它们的设计目的是为了提高字符串操作的效率,特别是在涉及大量字符串拼接的情况下。

主要区别在于它们的线程安全性:

  1. StringBuilder: 是非线程安全的,适用于单线程环境下的字符串拼接。由于不需要考虑线程同步的开销,通常比StringBuffer性能稍好。

    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("Hello");
    stringBuilder.append(" ");
    stringBuilder.append("World");
    String result = stringBuilder.toString();
    
  2. StringBuffer: 是线程安全的,适用于多线程环境下的字符串拼接。它使用了同步方法,因此在多线程情况下可以确保操作的原子性,但这也导致了一些性能开销。

    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer.append("Hello");
    stringBuffer.append(" ");
    stringBuffer.append("World");
    String result = stringBuffer.toString();
    
    

在实际使用中,如果你的应用是单线程的,建议使用StringBuilder,因为它相对更轻量。如果涉及到多线程操作,并且需要保证线程安全性,可以选择使用StringBuffer。总的来说,在大多数情况下,StringBuilder更常见,因为很多场景下不需要关心线程安全性。

5.2 字符串比较的最佳实践

在Java中进行字符串比较时,有几种不同的方法,而选择哪种方法通常取决于你的具体需求。

下面是一些在Java中进行字符串比较的最佳实践

  1. 使用equals方法:

    String str1 = "Hello";
    String str2 = "World";
    
    if (str1.equals(str2)) {
        // 字符串相等
    }
    
    

    这是最基本的字符串比较方法。使用equals方法比较字符串的内容是否相同。

  2. 忽略大小写比较:

    String str1 = "Hello";
    String str2 = "hello";
    
    if (str1.equalsIgnoreCase(str2)) {
        // 忽略大小写,字符串相等
    }
    
    

    使用equalsIgnoreCase方法来执行大小写不敏感的比较。

  3. 使用compareTo方法:

    String str1 = "Hello";
    String str2 = "World";
    
    int result = str1.compareTo(str2);
    
    if (result == 0) {
        // 字符串相等
    } else if (result < 0) {
        // str1 小于 str2
    } else {
        // str1 大于 str2
    }
    
    

    compareTo方法返回一个整数,表示两个字符串的大小关系。

  4. 使用Objects.equals方法(防止空指针异常):

    String str1 = "Hello";
    String str2 = "World";
    
    if (Objects.equals(str1, str2)) {
        // 字符串相等,包括处理空指针异常
    }
    
    

    Objects.equals方法可以防止在比较时出现空指针异常。

  5. 使用StringUtils.equals方法(Apache Commons Lang库):

    import org.apache.commons.lang3.StringUtils;
    
    String str1 = "Hello";
    String str2 = "World";
    
    if (StringUtils.equals(str1, str2)) {
        // 字符串相等,包括处理空指针异常
    }
    
    

    如果你使用Apache Commons Lang库,可以使用其中的StringUtils.equals方法来进行字符串比较,它也能处理空指针异常。

六、案例分析与实例演示

6.1 实际代码示例:如何更好地使用String类

在Java中,String类是一个常用的类,用于表示字符串并提供了许多方法来处理字符串。

以下是一些使用String类的实际代码示例,展示了如何更好地利用该类的一些常见方法:

  1. 字符串的基本操作:
public class StringExample {
    public static void main(String[] args) {
        // 创建字符串
        String str1 = "Hello";
        String str2 = "World";

        // 字符串连接
        String result = str1 + ", " + str2;
        System.out.println(result);

        // 获取字符串长度
        int length = result.length();
        System.out.println("Length: " + length);

        // 字符串比较
        boolean isEqual = str1.equals(str2);
        System.out.println("Are strings equal? " + isEqual);

        // 忽略大小写比较
        boolean isEqualIgnoreCase = str1.equalsIgnoreCase("hello");
        System.out.println("Are strings equal (ignore case)? " + isEqualIgnoreCase);

        // 提取子字符串
        String substring = result.substring(0, 5);
        System.out.println("Substring: " + substring);

        // 查找字符或子字符串的位置
        int index = result.indexOf("World");
        System.out.println("Index of 'World': " + index);
    }
}

  1. 使用StringBuilder进行字符串拼接:
public class StringBuilderExample {
    public static void main(String[] args) {
        // 使用StringBuilder进行字符串拼接
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Hello");
        stringBuilder.append(", ");
        stringBuilder.append("World");

        // 转换为String
        String result = stringBuilder.toString();
        System.out.println(result);
    }
}

  1. 字符串的拆分与连接:
public class SplitJoinExample {
    public static void main(String[] args) {
        // 字符串拆分
        String names = "John,Jane,Jim";
        String[] nameArray = names.split(",");
        for (String name : nameArray) {
            System.out.println("Name: " + name);
        }

        // 字符串连接
        String joinedNames = String.join("-", nameArray);
        System.out.println("Joined Names: " + joinedNames);
    }
}

6.2 常见陷阱与解决方案

在Java中,String类是一个常用的类,但在使用过程中可能会遇到一些陷阱。以下是一些常见的String类使用陷阱及其解决方案:

  1. 字符串拼接的陷阱

    • 陷阱:使用+运算符进行字符串拼接时,每次拼接都会创建一个新的String对象,效率较低。
    • 解决方案:使用StringBuilder类进行字符串拼接,它是可变的,可以减少对象的创建。
    StringBuilder sb = new StringBuilder();
    sb.append("Hello");
    sb.append(" ");
    sb.append("World");
    String result = sb.toString();
    
    
  2. 字符串比较的陷阱

    • 陷阱:使用==比较字符串内容,这比较的是对象的引用而不是内容。
    • 解决方案:使用equals()方法进行字符串内容的比较。
    String str1 = "Hello";
    String str2 = new String("Hello");
    if (str1.equals(str2)) {
        // 内容相等
    }
    
    
  3. 不可变性的陷阱

    • 陷阱:String对象是不可变的,每次对字符串进行修改都会创建新的对象,可能导致性能问题。
    • 解决方案:如果需要频繁修改字符串,可以使用StringBuilderStringBuffer,它们是可变的。
    StringBuilder sb = new StringBuilder("Hello");
    sb.append(" World");
    String result = sb.toString();
    
    
  4. 空字符串处理的陷阱

    • 陷阱:未对空字符串进行判空处理可能导致空指针异常。
    • 解决方案:始终在使用字符串之前检查是否为null或空字符串。
    String str = ...; // 从其他地方获取的字符串
    if (str != null && !str.isEmpty()) {
        // 执行操作
    }
    
    
  5. 字符串常量池的陷阱

    • 陷阱:使用new String()方式创建字符串对象时,不会在常量池中进行缓存,可能导致不必要的内存消耗。
    • 解决方案:直接使用字符串字面量,或者使用intern()方法将字符串对象放入常量池。
    String str1 = "Hello"; // 位于常量池
    String str2 = new String("Hello").intern(); // 放入常量池
    
    

这些是一些常见的String类使用陷阱及其解决方案。在开发中,始终注意字符串的不可变性和性能问题,选择适当的方式来处理字符串操作。

盈若安好,便是晴天

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

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

相关文章

【小聆送书第二期】人工智能时代之AIGC重塑教育

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;正文&#x1f4dd;活动参与规则 参与活动方式文末详见。 &#x1f4cb;正文 AI正迅猛地…

倪海厦:教你正确煮中药,发挥最大药效

同样的一个汤剂&#xff0c;我开给你&#xff0c;你如果煮的方法不对&#xff0c;吃下去效果就没那么好。 所以&#xff0c;汤&#xff0c;取它的迅捷&#xff0c;速度很快&#xff0c;煮汤的时候还有技巧&#xff0c;你喝汤料的时候&#xff0c;你到底是喝它的气&#xff0c;…

自动驾驶学习笔记(十六)——目标跟踪

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo 社区开发者圆桌会》免费报名—>传送门 文章目录 前言 匹配关联 轨迹记录 状态预测 总结 前…

Stable Diffusion AI绘画系列【22】:国风美女写实系列

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

面向 AI 开发者的新型编程语言Mojo

文章目录 面向 AI 开发者的新型编程语言Mojo一、什么是mojoLLVMMLIR为什么选择Mojo&#x1f525; 二、Mojo安装系统要求安装步骤Mojo Visual Studio Code (VS Code) 扩展 安装 三、官方hello world交互式运行构建和运行Mojo源文件构建可执行的二进制 四、Mojo语言基础Mojo 语言…

微服务学习:Nacos配置中心

先打开Nacos&#xff08;详见微服务学习&#xff1a;Nacos微服务架构中的服务注册、服务发现和动态配置&Nacos下载&#xff09; 1.环境隔离&#xff1a; 新建命名空间&#xff1a; 记住命名空间ID&#xff1a; c82496fb-237f-47f7-91ed-288a53a63324 再配置 就可达成环…

智能仪表板DevExpress Dashboard v23.1 - 支持自定义样式创建

使用DevExpress Analytics Dashboard&#xff0c;再选择合适的UI元素&#xff08;图表、数据透视表、数据卡、计量器、地图和网格&#xff09;&#xff0c;删除相应参数、值和序列的数据字段&#xff0c;就可以轻松地为执行主管和商业用户创建有洞察力、信息丰富的、跨平台和设…

LeetCode(53)逆波兰表达式求值【栈】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 逆波兰表达式求值 1.题目 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 、-、* 和 / 。每个操…

vs2017+qt5.14.2遇到的问题

1、在安装qt插件后&#xff0c;导入pro文件时&#xff0c;报 msvc-version.conf loaded but QMAKE_MSC_VER isn’t set 修改E:\Qt\Qt5.14.2\5.14.2\msvc2017_64\mkspecs\common\msvc-version.conf文件中添加

了解一下分治算法

文章目录 分治算法 分治算法 分治算法基本介绍 分治法&#xff08;Divide-and-Conquer&#xff09;是一种很重要的算法。字面上的解释是"分而治之"&#xff0c;就是把一个复杂的问题分成两个或更多的相同或相似的子问题&#xff0c;再把子问题分成更小的子问题……直…

LeetCode力扣每日一题(Java):27、移除元素

一、题目 二、解题思路 1、我的思路 因为题目中说“元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。”也就是说&#xff1a; 输入&#xff1a;nums [3,2,2,3], val 3 输出&#xff1a;2, nums [2,2] 解释&#xff1a;函数应该返回新的长度 2并且 nums 中的…

php循环遍历删除文件下文件和目录

前言 今天在写一个demo的时候需要循环删除目录下文件。如下想删temp下文件和目录。 具体实现 private function deleteDir($dirPath){if (is_dir($dirPath)) {$contents scandir($dirPath);// 如果是空目录if (count($contents) 2) {rmdir($dirPath);return;}// 不是空目录f…

三菱FX系列PLC的无线通讯方案

产品型号&#xff1a;NET30-FX-W4 使用范围&#xff1a;用于三菱FX3U/3G/3S/2N/1N/1S等系列PLC通讯扩展 1、产品介绍 工业通讯桥接器&#xff08;NET30-FX-W4&#xff09;用于三菱FX系列PLC&#xff08;FX3U/3G/3S/2N/1N/1S&#xff09;以及汇川、禾川等PLC的通讯扩展&#x…

JavaScript中的发布订阅和观察者模式:如何优雅地处理事件和数据更新

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript-订阅观察者模式 目录 说说你对发布订阅、观察者模式的理解&#xff1f;…

线边仓到底谁来管比较好

最近这段时间在客户现场出差&#xff0c;和客户聊到系统的边界时&#xff0c;客户IT希望将线边仓也纳入WMS进行管理。 给出的理由是WMS是管理实物的&#xff0c;线边仓也有实物存放&#xff0c;理所当然应该让WMS进行管理。 那线边仓能在WMS管理吗&#x…

【Python数据结构与算法】—— 搜索算法 | 期末复习不挂科系列

​ &#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 数据结构与算法&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 这篇博客主要探索的是计算机科学常见问题---搜索算法 “时间紧&#xff0c;任务重&#xff01;” 话不多说&#xff0c;开始今天…

力扣刷题总结 字符串(2)【KMP】

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 28.找出字符串中第一个匹配项的下标mid经典KMP4593重复的子字符串mid可以使用滑动窗口或者KMP KMP章节难度较大&#xff0c;需要深入理解其中…

轻量封装WebGPU渲染系统示例<44>- 材质组装流水线(MaterialPipeline)灯光、阴影、雾(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/MaterialPipelineFog.ts 当前示例运行效果: 主要的WGSL Shader代码: export class MaterialPipelineFog {private mRscene new RendererScene();initialize(): voi…

12.8IEEE 2023 |SZ3:一种基于预测的误差有界有损压缩器的模块化框架——文档记录

IEEE 2023 |SZ3&#xff1a;一种基于预测的误差有界有损压缩器的模块化框架 作者&#xff1a;START团队-贾轲 随着在高精尖计算设备上不断进行的百万兆级计算实验的增加&#xff0c;由此产生的计算数据规模与大小越来越夸张与庞大。因此&#xff0c;数据压缩对科学研究的重要…