Typescript高级: 对泛型和多态的应用, 实现Java中的ArrayList和LinkedList

本文主要是介绍Typescript高级: 对泛型和多态的应用, 实现Java中的ArrayList和LinkedList,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ArrayList


1 ) 概述

  • 在Java中,ArrayList是一个非常常用且强大的数据结构,它提供了动态数组的功能
  • 能够方便地添加、删除和访问元素。在TypeScript中,虽然并没有内置的ArrayList类型
  • 但我们可以通过类与接口来模拟实现ArrayList的功能

2 )实现

interface List<T> {size: number;add(item: T): void;get(index: number): T | undefined;remove(item: T): boolean;show(): void;
}class ArrayList<T> implements List<T> {public array: T[];private index: number = 0;public size: number = 0;constructor() {this.array = [];}// 添加元素,重载 add 方法add(item: T): void;add(item: any): void;add(item: number): void;add(item: string): void;add(item: any): void {this.array.push(item);this.size++;this.index = this.array.length; // 更新索引为数组最后一个元素的索引+1}// 获取元素get(index: number): T | undefined {return this.array[index];}// 删除元素,重载 remove 方法remove(item: T): boolean;remove(item: any): boolean;remove(item: number): boolean;remove(item: string): boolean;remove(item: any): boolean {const index = this.array.indexOf(item);if (index !== -1) {this.array.splice(index, 1);this.size--;return true;}return false;}// 显示全部数据show(): void {console.log(this.array);}// 更新元素,这里并没有在接口中定义,作为额外功能添加update(index: number, newValue: T): boolean {if (index >= 0 && index < this.size) {this.array[index] = newValue;return true;}return false;}
}const arrayList = new ArrayList<string>();// 添加元素
arrayList.add("Hello");
arrayList.add("World");
arrayList.add(42); // 这将不会报错,因为 TypeScript 中的泛型在运行时会被擦除,并且 add 方法被重载以接受 any 类型// 显示元素
arrayList.show(); // 输出: [ 'Hello', 'World', 42 ]// 获取元素
console.log(arrayList.get(0)); // 输出: Hello// 更新元素
arrayList.update(1, "TypeScript");
arrayList.show(); // 输出: [ 'Hello', 'TypeScript', 42 ]// 删除元素
console.log(arrayList.remove("TypeScript")); // 输出: true
arrayList.show(); // 输出: [ 'Hello', 42 ]// 获取数组大小
console.log(arrayList.size); // 输出: 2

3 )说明

  • 在基础List类型中,我们定义了如下方法和属性

    • add(item: T): 添加一个元素到ArrayList中
    • get(index: number): 根据索引获取元素
    • size: 存储ArrayList中元素的数量
    • remove(item: T): 删除一个元素
    • show(): 显示ArrayList中的所有元素
  • ArrayList 这个类继承List接口,并实现其所有的方法

  • 这里面实现了方法的多态和泛型

    • 1 )多态(Polymorphism)的主要优势在于提高了代码的可维护性和扩展性
    • 通过使用多态,我们可以编写更加灵活和可重用的代码
    • 因为我们可以定义通用的接口或方法,而不必关心具体实现细节
    • 2 ) 泛型(Generics)是TypeScript中一种强大的工具
    • 它允许我们在不丢失类型信息的前提下,编写可重用的组件
    • 这些组件可以与多种不同的类型一起工作,而不仅仅是一个类型
    • 泛型的主要作用是提供类型安全,同时确保代码的可复用性
    • 通过使用泛型,我们可以在保证类型安全的同时
    • 让函数与多种类型一起工作
  • 总结来说

    • 泛型和多态是TypeScript中两个强大的特性
    • 它们分别通过提供类型安全和允许统一操作不同数据类型来增强代码的可复用性和灵活性
    • 在实际开发中,结合使用泛型和多态可以帮助我们编写更加健壮、可维护和可扩展的代码

LinkedList


1 ) 概述

  • 在TypeScript中,实现一个双向链表(Doubly Linked List)相比于ArrayList会更加复杂
  • 因为我们需要维护每个节点的两个指针:一个指向前一个节点,另一个指向下一个节点
  • 同时,我们还要确保List接口的所有方法都能得到正确实现
  • 在数据结构中,链表是一种动态分配内存空间的线性数据结构
  • 由一系列的节点组成,每个节点通常包含两部分:
    • 一部分用于存储数据
    • 另一部分用于存储指向下一个节点的指针
  • 而双向链表,顾名思义,就是每个节点不仅包含指向下一个节点的指针
  • 还包含指向前一个节点的指针, 这使得双向链表在插入和删除节点时更为灵活

2 )实现

interface List<T> {add(element: T): void;get(index: number): T | undefined;size: number;remove(element: T): boolean;
}class N<T> {value: T;next: N<T> | null;prev: N<T> | null;constructor(value: T, next: N<T> | null = null, prev: N<T> | null = null) {this.value = value;this.next = next;this.prev = prev;}
}class LinkedList<T> implements List<T> {private head: N<T> | null = null;private tail: N<T> | null = null;public size = 0;add(element: T): void {const newNode = new N(element, null, this.tail);if (this.tail) {this.tail.next = newNode;} else {this.head = newNode;}this.tail = newNode;this.size++;}get(index: number): T | undefined {if (index < 0 || index >= this.size) {return undefined;}let current = this.head;for (let i = 0; i < index; i++) {current = current!.next;}return current?.value;}remove(element: T): boolean {let current = this.head;while (current) {if (current.value === element) {if (current.prev) {current.prev.next = current.next;} else {this.head = current.next;}if (current.next) {current.next.prev = current.prev;} else {this.tail = current.prev;}this.size--;return true;}current = current.next;}return false;}
}// 使用示例
const linkedList = new LinkedList<number>();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
console.log(linkedList.get(1)); // 输出: 2
console.log(linkedList.size); // 输出: 3
linkedList.remove(2);
console.log(linkedList.get(1)); // 输出: 3

3 )说明

  • 首先,我们定义了一个 List 接口,它规定了链表需要实现的基本方法:

    • 添加元素(add)
    • 获取指定位置的元素(get)
    • 获取链表大小(size)
    • 以及删除元素(remove)
    • 这个接口为后续的链表实现提供了统一的规范
  • 在 LinkedList 的实现中,节点被定义为一个名为 N 的内部类

    • 每个节点包含三个属性:value 用于存储数据,next 指向下一个节点,prev 指向前一个节点
    • 这样的结构使得链表能够双向遍历,从而更容易实现某些操作,如删除节点
  • LinkedList 类实现了 List 接口,并包含了维护链表状态的重要属性

    • head 指向链表的第一个节点,tail 指向链表的最后一个节点,size 记录链表的大小
  • 添加元素:add 方法在链表尾部添加一个新节点

    • 首先,创建一个新的节点,并设置其 next 为 null,prev 为当前的尾节点
    • 然后,更新尾节点为新节点,并如果原链表为空(即 head 和 tail 都为 null)
    • 则将 head 也指向新节点, 最后,链表的大小加一
  • 获取元素:get 方法通过遍历链表找到指定位置的元素

    • 它首先检查索引是否合法,然后从 head 开始遍历,直到找到对应位置的节点或遍历完整个链表
    • 这个过程的时间复杂度是 O(n),其中 n 是链表的大小
  • 删除元素:remove 方法遍历链表,查找并删除指定的元素

    • 当找到匹配的节点时,它更新相邻节点的指针以跳过该节点
    • 并调整 head 或 tail 如果被删除的是头节点或尾节点。最后,链表的大小减一
  • 总结

    • 双向链表 LinkedList 的实现简单而高效,通过双向指针实现了灵活的节点操作
    • 它的主要优势在于插入和删除节点时的性能,尤其是当需要在特定位置进行这些操作时
    • 然而,链表在随机访问元素方面的性能不如数组,因为需要从链表头部开始遍历以找到指定位置的元素
    • 在实际应用中,链表通常用于需要频繁插入和删除元素的场景,如实现缓存、LRU(最近最少使用)算法等
    • 而数组则更适用于需要频繁访问元素的场景,如搜索、排序等
    • 因此,在选择使用链表还是数组时,需要根据具体的应用场景和需求进行权衡

这篇关于Typescript高级: 对泛型和多态的应用, 实现Java中的ArrayList和LinkedList的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983930

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法