Android Glide, first start based on loadThumbnail, Kotlin(二)

Android Glide, first start based on loadThumbnail, Kotlin(二)

 

Android Glide, first start based on loadThumbnail, Kotlin(一)中有个小问题,通过loadThumbnail()采集到的缩略图真的就是整张图片的完整缩略图,直接放在正方形小格子里面,明显看到左右或者上下有空隙,因此,现在对这一情况改善,对loadThumbnail采集到的缩略图拉伸成标准的正方形图。

 

import android.content.ContentValues
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.view.setPadding
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormatclass MainActivity : AppCompatActivity() {companion object {const val TAG = "glide-fly"const val SIZE = 450const val VIEW_TYPE = 0const val DATE_TYPE = 1const val SPAN_COUNT = 6const val PAD_SIZE = 1var FIRST_START = true}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val rv: RecyclerView = findViewById(R.id.rv)rv.setHasFixedSize(true)rv.setItemViewCacheSize(SPAN_COUNT * 10)/*rv.setRecyclerListener(object : RecyclerListener {override fun onViewRecycled(holder: RecyclerView.ViewHolder) {if ((holder as MyVH).itemView is MyIV) {GlideApp.with(holder.itemView.context).clear(holder.itemView)}}})*/val layoutManager = MyGridLayoutManager(this, SPAN_COUNT)layoutManager.orientation = LinearLayoutManager.VERTICALrv.layoutManager = layoutManagerval adapter = MyAdapter(this)rv.adapter = adapterlifecycleScope.launch(Dispatchers.IO) {val items = readAllImage(this@MainActivity)items.sortByDescending {it.dateModified}val lists = items.distinctBy {it.dateString}lists.forEach { it_lists ->val idx = items.indexOfFirst {it_lists.dateString == it.dateString}val data = MyData()data.type = DATE_TYPEdata.dateString = it_lists.dateStringitems.add(idx, data) //不要直接加 it_Lists,这里面涉及到List的深拷贝/浅拷贝问题。}withContext(Dispatchers.Main) {adapter.dataChanged(items)}}layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {override fun getSpanSize(position: Int): Int {return if (adapter.getItemViewType(position) == DATE_TYPE) {//group,标题SPAN_COUNT} else {//单个小格子1}}}}class MyGridLayoutManager : GridLayoutManager {constructor(ctx: Context, cnt: Int) : super(ctx, cnt) {}override fun getExtraLayoutSpace(state: RecyclerView.State?): Int {return 1000}}class MyAdapter : RecyclerView.Adapter<MyVH> {private var mItems = arrayListOf<MyData>()private var mContext: Context? = nullprivate var mPlaceholder: Drawable? = nullprivate var mError: Drawable? = nullconstructor(ctx: Context) {mContext = ctxmPlaceholder = ContextCompat.getDrawable(mContext!!, android.R.drawable.ic_menu_gallery)mError = ContextCompat.getDrawable(mContext!!, android.R.drawable.stat_notify_error)}fun dataChanged(items: ArrayList<MyData>) {this.mItems = itemsnotifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {var v: View?if (viewType == VIEW_TYPE) {v = MyIV(mContext!!)} else {v = LayoutInflater.from(mContext!!).inflate(android.R.layout.simple_list_item_1, null)v.setBackgroundColor(Color.LTGRAY)}return MyVH(v!!)}override fun getItemCount(): Int {return mItems.size}override fun getItemViewType(position: Int): Int {return mItems[position].type}private fun getImageUri(context: Context, filePath: String): Uri? {val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,arrayOf(MediaStore.Images.Media._ID),MediaStore.Images.Media.DATA + "=? ",arrayOf(filePath),null)return if (cursor != null && cursor.moveToFirst()) {val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))val baseUri = Uri.parse("content://media/external/images/media")Uri.withAppendedPath(baseUri, "" + id)} else {val values = ContentValues()values.put(MediaStore.Images.Media.DATA, filePath)context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)}}override fun onBindViewHolder(holder: MyVH, position: Int) {val type = getItemViewType(position)if (type == VIEW_TYPE) {val path = mItems[holder.adapterPosition].pathval miv = holder.itemView as MyIVif (position > 50) {FIRST_START = false}if (FIRST_START && position < 50) {miv.setImageDrawable(mPlaceholder)val uri = getImageUri(mContext!!, path!!)QuickLoader.Instance().start(mContext!!, uri!!, miv)} else {GlideApp.with(mContext!!).asBitmap().load(path).centerCrop().override(SIZE).placeholder(mPlaceholder).error(mError).into(miv)}} else if (type == DATE_TYPE) {holder.itemView.findViewById<TextView>(android.R.id.text1).text = "${mItems[position].dateString}"}}}class MyVH : RecyclerView.ViewHolder {constructor(itemView: View) : super(itemView) {}}class MyIV : AppCompatImageView {constructor(ctx: Context) : super(ctx) {setPadding(PAD_SIZE)}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)val w = MeasureSpec.getSize(widthMeasureSpec)val h = MeasureSpec.getSize(heightMeasureSpec)val size = Math.max(w, h) //取w,h的最大值。setMeasuredDimension(size, size) //使得ImageView为正方形。}}class MyData {var type = VIEW_TYPEvar dateModified: Long? = 0Lvar dateString: String? = nullvar path: String? = nullvar index: Int? = nulloverride fun toString(): String {return "MyData(type=$type, dateModified=$dateModified, dateString=$dateString, path=$path, index=$index)"}}private fun readAllImage(context: Context): ArrayList<MyData> {val photos = ArrayList<MyData>()//读取所有图片val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null)var index = 0val sdf = SimpleDateFormat("yyyy-MM-dd")while (cursor!!.moveToNext()) {//路径 urival path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))if (TextUtils.isEmpty(path)) {continue}val dateModified = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_MODIFIED))//图片名称//val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))//图片大小//val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))val dateStr = sdf.format(dateModified?.toLong()!! * 1000)val data = MyData()data.type = VIEW_TYPEdata.path = pathdata.dateModified = dateModified.toLong()data.dateString = dateStrdata.index = index++photos.add(data)}cursor.close()return photos}
}

 

 

 

 

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.RectF
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.util.Size
import androidx.appcompat.app.AppCompatActivity
import com.pkg.name0220.MainActivity.Companion.SIZE
import java.util.concurrent.Executors
import kotlin.math.minclass QuickLoader {private var mHandler: MsgHandler? = nullcompanion object {const val THREAD_NUMBER = 4const val WHAT = 0xf01private val inst by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { QuickLoader() }fun Instance() = inst/*** 把采集到的缩略图(可能是瘦长的,也可能是矮平的)拉伸为宽高为标准MainActivity.SIZE的Bitmap。* 注意:Bitmap的API函数createScaledBitmap()相对耗时更多。*/fun scale(srcBmp: Bitmap): Bitmap {val t = System.currentTimeMillis()val bmp = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888)val c = Canvas(bmp)val width: Int = srcBmp.widthval height: Int = srcBmp.heightval bmpCenterX: Float = width / 2fval bmpCenterY: Float = height / 2fval minVal = min(width, height)val srcRectF = RectF(bmpCenterX - minVal / 2,bmpCenterY - minVal / 2,bmpCenterX + minVal / 2,bmpCenterY + minVal / 2)val dstRectF = RectF(0f, 0f, SIZE.toFloat(), SIZE.toFloat())val matrix = Matrix()//把bitmap中心区域的那一块放到目标的dstRectF里面。matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.CENTER)c.drawBitmap(srcBmp, matrix, null)Log.d("耗时", "scale=${System.currentTimeMillis() - t}")return bmp}}private constructor() {Log.d(MainActivity.TAG, "QuickLoader 初始化")mHandler = MsgHandler()}fun start(ctx: Context, uri: Uri, miv: MainActivity.MyIV) {val msg = mHandler?.obtainMessage(WHAT)msg?.obj = LoadTask(ctx, uri, miv)mHandler?.sendMessage(msg!!)}private class MsgHandler : Handler {private var mExecutorService = Executors.newFixedThreadPool(THREAD_NUMBER)constructor() : super(Looper.getMainLooper()) {Log.d(MainActivity.TAG, "MsgHandler 初始化")}override fun handleMessage(msg: Message) {mExecutorService.execute(msg.obj as LoadTask)}fun destroy() {removeMessages(WHAT)mExecutorService.shutdownNow()mExecutorService = null}}class LoadTask(private val ctx: Context, private val uri: Uri, private val miv: MainActivity.MyIV) : Runnable {override fun run() {Log.d(MainActivity.TAG, "run $uri")val t = System.currentTimeMillis()val bmp = ctx.contentResolver?.loadThumbnail(uri, Size(MainActivity.SIZE, MainActivity.SIZE), null)Log.d(MainActivity.TAG, "LoadTask 耗时:${System.currentTimeMillis() - t} $uri")(ctx as AppCompatActivity).runOnUiThread {miv.setImageBitmap(scale(bmp!!))}}}fun destroy() {mHandler?.destroy()mHandler = null}
}

 

 

 

 

 

 

 

 

Android矩阵Matrix setRectToRect实现标准scaleType中心缩放centerCrop,Kotlin-CSDN博客文章浏览阅读516次,点赞15次,收藏13次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大小对应的坐标区域显示“剪切”出来的圆形图。https://blog.csdn.net/zhangphil/article/details/139753381

Android Glide, first start based on loadThumbnail, Kotlin(一)-CSDN博客文章浏览阅读642次,点赞13次,收藏12次。【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。Android 13手机图片存储File路径转Uri,Java_android file 转uri-CSDN博客。文章浏览阅读690次。https://blog.csdn.net/zhangphil/article/details/139743546

Android简单把高大于宽或宽大于高的图从中心截成正方形,Kotlin-CSDN博客文章浏览阅读744次,点赞9次,收藏12次。Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin_bitmapfactory解码宽高-CSDN博客。Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客。实现的是把原图中心区域的一片小图挖取出来放大放到下面的ImageView里面,现在不再固定中心位置,而是以手指在上图的触点位置为中心位置,挖取一片区域图放大,然后放到下面的ImageView里面。https://blog.csdn.net/zhangphil/article/details/139181062

Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(二)_android bitmap 动画-CSDN博客文章浏览阅读770次,点赞4次,收藏5次。【代码】Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(二)_android bitmap 动画https://blog.csdn.net/zhangphil/article/details/135992780Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(一)_android matrix setrecttorect-CSDN博客文章浏览阅读1.2k次,点赞14次,收藏8次。基于Matrix,控制Bitmap的setRectToRect的目标RectF的宽高。从很小的宽高开始,不断迭代增加setRectToRect的目标RectF的宽高,每次迭代加上一定时延,实现Matrix基础上的动画。文章浏览阅读180次。【代码】Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin。Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客。_android matrix setrecttorecthttps://blog.csdn.net/zhangphil/article/details/135980821Android矩阵Matrix变换setRectToRect,Kotlin_android rect 矩阵-CSDN博客文章浏览阅读709次,点赞7次,收藏8次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大小对应的坐标区域显示“剪切”出来的圆形图。_android rect 矩阵https://blog.csdn.net/zhangphil/article/details/135913218

Android矩阵Matrix裁切setRectToRect拉伸Bitmap替代Bitmap.createScaledBitmap缩放,Kotlin-CSDN博客文章浏览阅读1.1k次,点赞7次,收藏14次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大小对应的坐标区域显示“剪切”出来的圆形图。_createscaledbitmaphttps://blog.csdn.net/zhangphil/article/details/135961734

 

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

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

相关文章

C语言入门系列:数据类型之布尔类型

文章目录 1&#xff0c;以前&#xff0c;C语言没有布尔类型2&#xff0c;后来&#xff0c;C语言假装有了布尔类型3&#xff0c;再后来&#xff0c;C语言的非标布尔类型 1&#xff0c;以前&#xff0c;C语言没有布尔类型 其实&#xff0c;C 语言没有真正的布尔类型&#xff0c;…

STM32通过I2C软件读写MPU6050

文章目录​​​​​​​ 1. MPU6050 1.1 运动学概念 1.2 工作原理 2. 参数 2.1 量程选择 2.2 I2C从机地址配置 3. 硬件电路 4. 框架图 5. 软件和硬件波形对比 6. 软件I2C读写MPU6050 6.1 程序整体构架 6.2 一些需要注意的点&#xff1a; 6.3 MPU6050初始化配置 6…

支持 MKV、MP4、AVI、MPG 等格式视频转码器

一、简介 1、一款开源的视频转码器&#xff0c;适用于 Linux、Mac 和 Windows。它是一个免费的工具&#xff0c;由志愿者们开发&#xff0c;可以将几乎所有格式的视频转换为现代、广泛支持的编码格式。你可以在官网上下载该应用或源代码。该软件支持 MKV、MP4、AVI、MPG 等格式…

如何计算文档会消耗的Token数量?

在AI的世界里&#xff0c;"token"就像是把我们说的话或写的文字拆分成的小块块&#xff0c;每块可以是一个词、一个短语、一个标点&#xff0c;甚至一个字母。不同的AI系统可能有不同的拆分方法。 阿里云的灵积平台有个工具&#xff0c;叫做Token计算器。这个工具就…

经常混淆的ADC输入类型!

大家好,这里是大话硬件。 这篇文章我们来聊聊ADC的输入类型。 ADC的输入类型根据ADI的官网,分为了3种类型,单端,差分,伪差分。如下图快速选型的界面所示。 同时,TI的官网对ADC的输入类型划分也是同样的3种类型。 可见,两个器件厂家对ADC的输入类型都是这样定义的。 …

springMVC的bug

写SpringMVC时&#xff0c;配置视图解析器路径中少写了个“/”导致url拼接错误&#xff0c;无法返回视图

支持向量机 (SVM) 算法详解

支持向量机 (SVM) 算法详解 支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种监督学习模型&#xff0c;广泛应用于分类和回归分析。SVM 特别适合高维数据&#xff0c;并且在处理复杂非线性数据时表现出色。本文将详细讲解 SVM 的原理、数学公式、应用场景…

项目中选择Entity Framework Core还是Dapper?

我是将 Dapper 还是 Entity framework core 用于下一个 .NET 项目&#xff1f;当你必须做出这个决定时&#xff0c;总是令人困惑&#xff0c;为了项目的成功&#xff0c;你需要做出正确的决定。让我来帮你... 介绍 使用 .NET 开发的应用程序可以根据其使用的对象关系映射器 &…

Java | Leetcode Java题解之第168题Excel表列名称

题目&#xff1a; 题解&#xff1a; class Solution {public String convertToTitle(int columnNumber) {StringBuffer sb new StringBuffer();while (columnNumber ! 0) {columnNumber--;sb.append((char)(columnNumber % 26 A));columnNumber / 26;}return sb.reverse().t…

【APP移动端性能测试】第一节.APP应用架构、环境和敏捷开发模型介绍

文章目录 前言一、APP应用架构二、APP项目环境 2.1 后端项目环境 2.2 前端项目环境三、Scrum敏捷开发模型 3.1 Scrum敏捷模型基础介绍 3.2 Scrum敏捷开发开发流程总结 前言 一、APP应用架构 &#xff08;1&#xff09;APP应用架构 &#xff08;2&#xff0…

springboot应用cpu飙升的原因排除

1、通过top或者jps命令查到是那个java进程&#xff0c; top可以看全局那个进程耗cpu&#xff0c;而jps则默认是java最耗cpu的&#xff0c;比如找到进程是196 1.1 top (推荐)或者jps命令均可 2、根据第一步获取的进程号&#xff0c;查询进程里那个线程最占用cpu&#xff0c;发…

js 用正则表达式 匹配自定义字符之间的字符串数据,如:( )、[ ]、{ }、< >、【】等括号之间的字符串数据

要使用正则表达式匹配尖括号()之间的数据&#xff0c;可以使用以下代码示例&#xff1a; 在JavaScript中&#xff0c;你可以使用正则表达式来匹配括号()之间的数据。以下是一个简单的例子&#xff0c;它展示了如何使用正则表达式来获取两对括号之间的文本。 // 示例字符串 con…

LENOVO联想 小新 16 IAH8 2023款(83BG)笔记本原厂Windows11系统,恢复出厂开箱状态预装OEM系统镜像安装包下载

适用型号&#xff1a;小新 16 IAH8【83BG】 链接&#xff1a;https://pan.baidu.com/s/18VbGbBXtQEW5P8wLIyJtAQ?pwddv1s 提取码&#xff1a;dv1s 联想原装Win11系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office办公软件、联想电脑管家…

董宇辉的人生关键词:年轻人的成长指南

在当今这个信息爆炸、竞争激烈的社会中&#xff0c;年轻人面临着前所未有的挑战与机遇。如何从纷繁复杂的世界中找到属于自己的道路&#xff1f;近日&#xff0c;知名人生导师董宇辉为年轻人提出了几个人生关键词&#xff0c;这些词汇不仅凝聚了他多年的人生感悟&#xff0c;更…

【STM32-ST-Link】

STM32-ST-Link ■ ST-Link简介■ ST-Link驱动的安装。■ ST-Link编程软件(MDK)配置。■ ST-Link固件升级方法 ■ ST-Link简介 由于德产 J-LINK 价格非常昂贵&#xff0c; 而国产 J-LINK 因为版权问题将在万能的淘宝销声匿迹。 所以我们有必要给大家介绍 JTAG/SWD 调试工具中另…

如何做好技术管理与技术规划?

一、背景 做好技术管理不仅要求紧跟行业前沿动态&#xff0c;同时也需把握好产品开发的阶段性分期&#xff0c;确保技术成果转化和产品落地的顺畅进行。技术管理的成功与否&#xff0c;在很大程度上取决于能否精准捕捉市场需求&#xff0c;据此调整任务优先级。面对瞬息万变的…

Day10—Spark SQL基础

Spark SQL介绍 ​ Spark SQL是一个用于结构化数据处理的Spark组件。所谓结构化数据&#xff0c;是指具有Schema信息的数据&#xff0c;例如JSON、Parquet、Avro、CSV格式的数据。与基础的Spark RDD API不同&#xff0c;Spark SQL提供了对结构化数据的查询和计算接口。 Spark …

IDEA上MySQL的jar包导入教程

jar包下载网址——》https://mvnrepository.com/ 1.进入界面&#xff0c;点击搜索框&#xff0c;搜索mysql&#xff1a; 外国网站&#xff0c;可能有点慢,耐心等待即可。 2.点击查询结果&#xff1a; 进入界面&#xff0c;点击前两个结果的其中一个&#xff0c;两个都可以 …

计算机毕业设计Python+Vue.js+Flask+Scrapy电影大数据分析 电影推荐系统 电影爬虫可视化 电影数据分析 大数据毕业设计 协同过滤算法

开发技术 协同过滤算法、机器学习、vue.js、echarts、Flask、Python、MySQL 创新点 协同过滤推荐算法、爬虫、数据可视化 补充说明 两种Python协同过滤推荐算法集成 (ItemCF推荐算法 和 UserCF 推荐算法) 2.专业美工整体设计的细腻的酷黑主题&#xff0c;前后端分离一体化系统&…

leetCode-hot100-链表专题

leetCode-hot100-链表专题 链表简介单链表单链表的使用例题206.反转链表19.删除链表的倒数第N个结点24.两两交换链表中的节点25.K个一组翻转链表 双向链表双向链表的使用 循环链表61.旋转链表141.环形链表142.环形链表Ⅱ LinkedListLinkedList的使用 链表简介 参考博客&#x…