Java 集合进阶(二)

news2024/11/15 8:56:26

文章目录

    • 一、Set
      • 1. 概述
      • 2. 哈希值
      • 3. 元素唯一性
      • 4. 哈希表
      • 5. 遍历学生对象
      • 6. LinkedHashSet
      • 7. TreeSet
        • 7.1 自然排序
        • 7.2 比较器排序
      • 8. 不重复的随机数
    • 二、泛型
      • 1. 概述
      • 2. 泛型类
      • 3. 泛型方法
      • 4. 泛型接口
      • 5. 类型通配符
      • 6. 可变参数
      • 7. 可变参数的使用

一、Set

1. 概述

Set 集合特点:
① 不包含重复元素的集合;
② 没有带索引的方法,所以不能使用普通 for 循环遍历;
③ HashSet 是 Set 的一个实现类,HashSet 对集合的迭代顺序不作任何保证,输出的元素可能是乱序的。

//Test.java

package com.an;

import java.util.HashSet;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        Set<String> set = new HashSet<String>();
        set.add("a");
        set.add("b");
        set.add("c");
        set.add("c");
        for (String s : set) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述

可以看到当出现重复的元素时,控制台只会输出一个!

2. 哈希值

哈希值是 JDK 根据对象的地址或者字符串或者数字算出来的 int 类型的数值

Object 类中有一个方法可以获取到对象的哈希值:

public int hashCode(); //返回对象的哈希码值
//Test.java

package com.an;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("刘德华", 50);
        System.out.println(s1.hashCode());
        System.out.println(s1.hashCode());
        Student s2 = new Student("张学友", 53);
        System.out.println(s2.hashCode());
    }
}

在这里插入图片描述

同一个对象多次调用 hashCode() 方法返回的哈希值是相同的,不同对象的哈希值在默认情况下是不相同的!

通过方法重写,可以使不同的对象拥有相同的哈希值:

 @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

在这里插入图片描述

在学生类里面 Alt + Insert,equals() and hasCode(),一直按下一步,这里会自动帮我们生成 equals() 方法和 hasCode() 方法,equals() 方法就是我们前面常用 API 里面讲过的用于比较两个对象是否相等,hasCode() 方法即可使不同的对象拥有相同的哈希值,return 后面的内容自定义。

3. 元素唯一性

在这里插入图片描述

HashSet 集合存储元素要保证元素的唯一性,就需要重写 equals() 方法和 hasCode() 方法!

4. 哈希表

JDK8 之前,底层采用数组+链表实现,可以说是一个元素为链表的数组;JDK8 以后,在长度比较长的时候,底层实现了优化。

在这里插入图片描述

① 存储地址即哈希值对 16 取余;
② 当存储地址相同时,先比较哈希值,哈希值不同直接存储;
③ 哈希值相同时,比较存储内容,存储内容不同直接存储,内容相同则不存储。

5. 遍历学生对象

需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合,当学生对象的成员变量值相同时,我们就认为是同一个对象。

//Student.java

package com.an;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return 2;
    }
}

//Test.java

package com.an;

import java.util.HashSet;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("刘德华", 50);
        Student s2 = new Student("张学友", 53);
        Student s3 = new Student("周杰伦", 46);
        Student s4 = new Student("周杰伦", 46);
        HashSet<Student> set = new HashSet<Student>();
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        for (Student s : set) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述

要注意,这里与我们前面说的元素唯一性是不同的,前面所讲是多次调用相同对象时,控制台不予输出,而本案例是当其成员变量的值相同时,我们就认为是同一个对象,就是说不会再控制台打印相同的内容。前者针对对象,后者针对内容,需在学生类中重写 equals() 及 hashCode()方法。

6. LinkedHashSet

LinkedHashSet 集合的特点:
① 由哈希表和链表实现的 Set 接口,具有可预测的迭代次序;
② 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的;
由哈希表保证元素唯一,也就是说没有重复元素。

LinkedHashSet<String> l = new LinkedHashSet<String>();

往集合里面添加元素,输出的结果有序且唯一!

7. TreeSet

TreeSet():根据其元素的自然排序进行排序;
TreeSet(Comparator comparator):根据指定的比较器进行排序。

TreeSet 集合的特点:
① 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法;
② 没有带索引的方法,所以不能使用普通 for 循环遍历;
③ 由于是 Set 集合,所以不包含重复元素的集合。

//Test.java

package com.an;

import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>();
        ts.add(10);
        ts.add(40);
        ts.add(30);
        ts.add(50);
        ts.add(20);
        for (Integer i : ts) {
            System.out.println(i);
        }
    }
}

在这里插入图片描述

可以看到这里遍历到的结果并不是按我们存取的顺序来取出的,这就是自然排序,从小到大排。

集合里面存储的只能是引用类型的元素,对于基本类型存储的时候,我们用的是它的包装类类型!

7.1 自然排序

需求:存储学生对象并遍历,创建 TreeSet 集合使用无参构造方法,要求按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序。

//Student.java

package com.an;

import java.util.Objects;

public class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public int compareTo(Student s) {
        int num = this.age - s.age;
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;
    }
}

//Test.java

package com.an;

import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("xishi", 20);
        Student s2 = new Student("zhangliang", 29);
        Student s3 = new Student("diaochan", 31);
        Student s4 = new Student("wuzetian", 34);
        Student s5 = new Student("lvbu", 31);
        Student s6 = new Student("xishi", 20);
        TreeSet<Student> ts = new TreeSet<Student>();
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        for (Student s : ts) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述

① Comparable 该接口对实现它的每个类的对象强加一个整体排序,这个排序被称为类的自然排序。也就是说,如果我们要对学生对象做自然排序,就必须让学生类去实现该接口;
② 这里实现接口的时候需要加泛型,然后在学生类里面重写 compareTo 方法;
③ 注意它的返回值,返回 0 重复元素不添加,返回正数按照升序存储,返回负数按照降序来存储;
④ 同时我们可以看到当两个对象的内容相同时,程序会认为是同一个对象,所以不会存储,保证了元素的唯一性;
⑤ 若按成绩、年龄等数字型变量排序,num 值是 s.age - this.age,若按非数字型标准排序,num 值是 s.name.compareTo(this.name);
⑥ 写出主要条件,不要忘了次要条件。

//1.升序排序
 public int compareTo(Student s) {
        int num = this.age - s.age;
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;
    }

//2.降序排序
 public int compareTo(Student s) {
        int num = s.age - this.age;
        int num2 = num == 0 ? s.name.compareTo(this.name) : num;
        return num2;
    }

在存储对象的时候,add() 方法内部会自动调用 compartTo() 方法!

7.2 比较器排序

需求:存储学生对象并遍历,创建 TreeSet 集合使用无参构造方法,要求按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序。

//Test.java

package com.an;

import java.util.Comparator;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });
        Student s1 = new Student("xishi", 20);
        Student s2 = new Student("zhangliang", 29);
        Student s3 = new Student("diaochan", 31);
        Student s4 = new Student("wuzetian", 34);
        Student s5 = new Student("lvbu", 31);
        Student s6 = new Student("xishi", 20);

        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        for (Student s : ts) {
            System.out.println(s);
        }
    }
}

① 学生类即基础学生类,比较器排序法不用在学生类中实现接口;
② 自然排序是在学生类中重写接口方法,比较器排序采用的是匿名内部类的方式,让集合构造方法接收 Comparator 的实现类对象,这两个方法的功能效果一模一样;
③ 注意测试类中访问成员变量要使用其 get 方法,设置了权限不能直接访问。

8. 不重复的随机数

需求:编写一个程序,获取 10 个 1~20 之间的随机数,要求随机数不能重复,并在控制台输出。

思路:
① 创建 Set 集合对象;
② 创建随机数对象;
③ 判断集合的长度是不是小于 10,如果小于 10 就产生一个随机数,添加到集合,通过循环不断判断,直到集合长度为 10;
④ 遍历集合。

//Test.java

package com.an;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        Set<Integer> s = new HashSet<>();
        Random r = new Random();
        while (s.size() < 10) {
            Integer random = r.nextInt(20) + 1;
            s.add(random);
        }
        for (Integer i : s) {
            System.out.println(i);
        }
    }
}

在这里插入图片描述

二、泛型

1. 概述

泛型是 JDK5 引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,它的本质是参数化类型,也就是说,所操作的数据类型被指定为一个参数。
一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,然后在使用 / 调用时传入具体的类型。
这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法和泛型接口。

泛型的定义格式:
① <类型>,指定一种类型的格式,这里的类型可以看成是形参;
② <类型1, 类型2 … >,指定多种类型的格式,多种类型之间用逗号隔开,这里的类型可以看成是形参;
③ 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型。

 Collection c = new ArrayList();

直接这样创建集合,集合对象默认的数据类型是 Object,所以遍历集合元素写 String 类型时就会报错,需要把 String 改成 Object 或者进行强制类型转换!

在这里插入图片描述

使用泛型后:

Collection<String> c = new ArrayList<String>();

泛型的好处:
① 把运行时期的问题提前到了编译期间;
② 避免了强制类型转换。

2. 泛型类

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
public class Generic<T> {}
//Generic.java

package com.an;

public class Generic<T> {
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

}

//Test.java

package com.an;

public class Test {

    public static void main(String[] args) {
        Generic<String> g1 = new Generic<>();
        g1.setT("熊二");
        System.out.println(g1.getT());

        Generic<Integer> g2 = new Generic<>();
        g2.setT(20);
        System.out.println(g2.getT());
    }
}

在这里插入图片描述

泛型类让我们传入的参数可以是任意类型的数据类型!

3. 泛型方法

public <T> void show(T t) {}
//Generic.java

package com.an;

public class Generic {
    public <T> T show(T t) {
        return t;
    }
}

//Test.java

package com.an;

public class Test {

    public static void main(String[] args) {
        Generic g = new Generic();
        System.out.println(g.show(2));
        System.out.println(g.show("hhhh"));
        System.out.println(g.show(false));
    }
}

在这里插入图片描述

任何类型均可满足,直到传入实参之后,形参的数据类型才被确定!

4. 泛型接口

public interface Generic<T> {}
//Generic.java

package com.an;

public interface Generic<T> {
    void show(T t);
}

//GenericImpl.java

package com.an;

public class GenericImpl<T> implements Generic<T> {
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

//Test.java

package com.an;

public class Test {

    public static void main(String[] args) {
        Generic<String> g1 = new GenericImpl<>();
        g1.show("world");
        Generic<Integer> g2 = new GenericImpl<>();
        g2.show(12);
    }
}

5. 类型通配符

为了表示各种泛型 List 的父类,可以使用类型通配符。

类型通配符:<?> List<?>:表示元素类型未知的 List,它的元素可以匹配任何的类型。

这种带通配符的 List 仅表示它是各种泛型 List 的父类,并不能把元素添加到其中!

如果说我们不希望 List<?> 是任何泛型 List 的父类,只希望它代表某一类泛型 List 的父类,可以使用类型通配符的上限。(它及其子类)

类型通配符上限:<? extends 类型>
List<? extends Number>:它表示的类型是 Number 或者其子类型

除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限。(它及其父类)

类型通配符下限:<? super 类型>
List<? super Number>:它表示的类型是 Number 或者其父类型。

//类型通配符
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
//类型通配符上限
List<? extends Number> list3 = new ArrayList<Number>();
List<? extends Number> list4 = new ArrayList<Integer>();
//类型通配符下限
List<? super Number> list5 = new ArrayList<Number>();
List<? super Number> list6 = new ArrayList<Object>();

6. 可变参数

可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了。

public static int sum(int... a) {}
//Test.java

package com.an;

public class Test {
    public static void main(String[] args) {
        System.out.println(sum(1, 2));
        System.out.println(sum(10, 2, 11, 9));
        System.out.println(sum(8, 21, 10));
        System.out.println(sum(2, 3, 8, 10, 10, 20));
    }

    public static int sum(int... a) {
        int sum = 0;
        for (int i : a) {
            sum += i;
        }
        return sum;
    }
}

在这里插入图片描述

可以看到不管传入多少个参数,我们始终只用一个 sum 方法即可,可变参数的好处就是使代码更加精简,这里 …a
实际上是把传入的数个参数都封装到一个数组中,而这个数组就是 a,求和?遍历数组然后累加。

如果一个方法中有多个参数,其中包含可变参数时,可变参数一定要放到最后,否则报错!

7. 可变参数的使用

//Test.java

package com.an;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

public class Test {
    public static void main(String[] args) {

//        1.返回由指定数组支持的固定大小的列表,不能增删可以修改
        List<String> l1 = Arrays.asList("I", "love", "you");
//        l1.add("w");
//        l1.remove("love");
        l1.set(0, "w");
        System.out.println(l1);

//        2.返回包含任意数量元素的不可变列表,不能增删改
        List<String> l2 = List.of("hello", "world", "hi", "world");
//        l2.add("hh");
//        l2.remove("hi");
//        l2.set(1, "abc");
        System.out.println(l2);

//        3.返回一个包含任意数量元素的不可变集合,不能增删改且元素不能重复
        Set<String> s = Set.of("I", "am", "a", "good", "man");
//        s.add("ai");
//        s.remove("I");
        System.out.println(s);
    }
}

在这里插入图片描述

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

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

相关文章

AI领域通识

人工智能的架构&#xff1a;通常来说&#xff0c;人工智能架构分为四层&#xff1a;最底层的基础层一般由软硬件设施以及数据服务组成。软件设施主要包括智能云平台和大数据平台&#xff0c;比如国外的谷歌大数据平台和国内的百度智能云平台等&#xff1b;硬件设施主要包括CPU硬…

讨论基于最新的(v5或v6版本)UXP插件开发的开发框架的选择问题

看过我的上两篇文章后&#xff0c;相信你对UXP的开发环境已经有一定了解了&#xff0c;然后这里讨论一个问题&#xff0c;UXP的开发可以基于纯htmlcssjs、vue框架、react框架、svelte框架&#xff0c;就是到底用哪种方式开发更好了&#xff1f;一般情况是用自己最熟悉的或者是使…

使用vue脚手架创建vue项目

大家好&#xff0c;这里是 一口八宝周 &#x1f44f;欢迎来到我的博客 ❤️一起交流学习文章中有需要改进的地方请大佬们多多指点 谢谢 &#x1f64f;使用脚手架创建vue项目步骤&#xff1a;切换淘宝镜像npm config set registry https://registry.npm.taobao.org安装脚手架npm…

算法拾遗二十七之窗口最大值或最小值的更新结构

算法拾遗二十七之窗口最大值或最小值的更新结构滑动窗口题目一题目二题目三题目四滑动窗口 第一种&#xff1a;R&#xff0c;R右动&#xff0c;数会从右侧进窗口 第二种&#xff1a;L&#xff0c;L右动&#xff0c;数从左侧出窗口 题目一 arr是N&#xff0c;窗口大小为W&…

C++ linux下获取时间戳 秒、微妙、纳秒

1.例子#include <iostream>#include <sys/time.h>#include <cstdlib>#include <cstdio>#include <ctime>#include <cmath>#include <unistd.h>usingnamespace std;time_t clocktime(){time_t t time(NULL);std::cout << &quo…

聚势合力,电巢与SDIA协会“战略合作签约仪式”圆满落成

前言&#xff1a; 2023年03月02日下午&#xff0c;电巢科技与深圳市平板显示行业协会齐聚深圳南山电巢XR演播厅&#xff0c;共同举办了隆重的战略合作签约仪式。 双方就数字化建设、品牌赋能、人才培养、技术创新等企业服务深入合作上达成一致&#xff0c;合力为产业赋能&…

【OJ比赛日历】快周末了,不来一场比赛吗? #03.11-03.17 #12场

CompHub 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号同时会推送最新的比赛消息&#xff0c;欢迎关注&#xff01;更多比赛信息见 CompHub主页 或 点击文末阅读原文以下信息仅供参考&#xff0c;以比赛官网为准目录2023-03-11&…

netty-websocket 鉴权token及统一请求和响应头(鉴权控制器)

自己想法和实现&#xff0c;如果有说错的或者有更好的简单的实现方式可以私信交流一下(主要是实现握手时鉴权) 需求实现 握手鉴权是基于前台请求头 Sec-WebSocket-Protocol的本身socket并没有提供自定义请求头&#xff0c;只能自定义 Sec-WebSocket-Protocol的自协议 问题描述…

你几乎不知道的浏览器内置对象/事件/ajax

浏览器内置对象/事件/ajax 浏览器是⼀个 JS 的运⾏时环境&#xff0c;它基于 JS 解析器的同时&#xff0c;增加了许多环境相关的内容。⽤⼀张图表示各个运⾏环境和 JS 解析器的关系如下&#xff1a; 我们把常⻅的&#xff0c;能够⽤ JS 这⻔语⾔控制的内容称为⼀个 JS 的运⾏环…

Leetcode—环形链表

前言&#xff1a;给定一个链表&#xff0c;判断是否为循环链表并找环形链表的入口点 首先我们需要知道什么是双向循环链表&#xff0c;具体如下图所示。 对于链表&#xff0c;我们如何去判断链表是循环链表呢&#xff1f;又寻找入环点呢&#xff1f;我们可以利用快慢指针的方法…

Meta CTO:Quest 2生命周期或比预期更久

前不久&#xff0c;Meta未来4年路线图遭曝光&#xff0c;泄露了该公司正在筹备中的一些AR/VR原型。除此之外&#xff0c;还有消息称Quest Pro或因销量不佳&#xff0c;而不再迭代。毫无疑问&#xff0c;Meta的一举一动持续受到行业关注&#xff0c;而面对最近的爆料&#xff0c…

关于指针运算的一道题

目录 刚看到这道题的时候我也和大多数小白一样感到无从下手&#xff0c;但是在我写这篇博客的前几分钟开始我对这道题有了一点点的理解。所以我就想着趁热打铁&#xff0c;写一篇博客来记录一下我的想法。 题目如下&#xff1a; 画图&#xff1a; 逐一解答&#xff1a; 题一…

笔记:二叉树

学习了二叉树&#xff0c;今天来整理一下笔记吧&#xff01;一&#xff1a;树的理解树的度是不限制的&#xff0c;一个双亲结点可以有很多子节点&#xff0c;但是子节点是不能交叉的&#xff0c;也就是不能有环。树的的最大层次叫做这棵树的深度或者高度&#xff1b;树的代码表…

高三应该怎么复习

高三是学生们备战高考的重要一年&#xff0c;正确有序的复习可以有效地提高复习效率&#xff0c;下面是一些高效复习的方法和建议&#xff1a;1. 制定合理的学习计划和目标高三的学生要制定合理的学习计划和目标&#xff0c;适当的计划和目标可以使学习更有针对性和效率。建议根…

本地部署dynamics

打开虚拟机的dynamics部署管理&#xff0c;点击组织再点击浏览 进入网址&#xff0c;输入账号密码 登录成功 点销售旁边的下箭头&#xff0c;选择设置中的系统作业 成功进入到系统作业 进入这个网址 Dynamics 365 客户参与快速入门&#xff08;本地&#xff09;&#xff08;Dy…

VRRP与BFD联动配置

VRRP与BFD联动配置 1. 实验目的 熟悉VRRP与BFD联动的应用场景掌握VRRP与BFD联动的配置方法2. 实验拓扑 实验拓扑如图14-13所示: 图14-13:VRRP与BFD联动配置 3. 实验步骤 配置IP地址PC1的配置 PC1的配置如图14-14所示:

Python 协程详解,都在这里了

什么是协程 协程&#xff08;co-routine&#xff0c;又称微线程、纤程&#xff09; 是一种多方协同的工作方式。 协程不是进程或线程&#xff0c; 其执行过程类似于 Python 函数调用&#xff0c; Python 的 asyncio 模块实现的异步IO编程框架中&#xff0c; 协程是对使用 asy…

毕设常用模块之舵机介绍以及使用方法

舵机 舵机是一种位置伺服的驱动器&#xff0c;主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机&#xff0c;其内部有一个基准电路&#xff0c;产生周期为 20ms&#xff0c;宽度为 1.5ms 的基准信号&#xff0c;将获…

易优cms user 登录注册标签

user 登录注册标签 user 登录注册入口标签 [基础用法] 标签&#xff1a;user 描述&#xff1a;动态显示购物车、登录、注册、退出、会员中心的入口&#xff1b; 用法&#xff1a; {eyou:user typeuserinfo} <div id"{$field.htmlid}"> …

如何用项目管理软件,帮助项目经理监控进度?

项目无论规模大小&#xff0c;都要处理许多任务&#xff0c;管理项目文档&#xff0c;监控任务进度等。 有一个方法可以帮助项目经理在制定计划和项目推进时确保一切保持井井有条。 项目管理软件是最有用的工具之一&#xff0c;通常被用于项目计划、时间管理等&#xff0c;能在…