Android Studio学习笔记——数据库存储

Android Studio学习笔记——数据库存储

  • 6.1持久化技术简介
  • 6.2 文件存储
    • 将数据存储到文件中
    • 从文件中读取数据
  • 6.3 SharedPreferences存储
    • 6.3.1 将数据存储到是SharedPreferences中
    • 6.3.2 从SharedPreferences中读取数据
    • 6.3.3 实现记住密码功能
  • 6.4 SQLite数据库存储
    • 6.4.1 创建数据库
    • 6.4.2 升级数据库
    • 6.4.3 添加数据
    • 6.4.4 更新数据
    • 6.4.5 删除数据
    • 6.4.6 查询数据
    • 6.4.7 使用SQL操作数据库
  • 6.5 使用LitePal操作数据库
    • 6.5.1 LitePal简介
    • 6.5.2 配置LitePal
    • 6.5.3 创建和升级数据库
    • 6.5.4 增加
    • 6.5.5 更新
    • 6.5.6 删除
    • 6.5.6 查询

数据持久化技术就是将内存中瞬时数据保存到存储设备中,保证关机或者重启之后不会数据丢失。

6.1持久化技术简介

Android中主要提供了三种方式用于简单的实现数据持久化功能,即文件存储、SharedPreference存储以及数据库存储。除此之外,还有其他方式,比如说存在SD卡中。文件存储、SharedPreference存储以及数据库存储这三种比存在SD卡中简单,而且更安全。

6.2 文件存储

文件存储不对数据进行任何格式化的处理,适合存储一些简单的文本数据或二进制数据。如果想要存储复杂的数据,就要自定义一套自己的格式规范,这样以后方便从文件中重新解析出来。

将数据存储到文件中

Context类提供了一个openFileOutput()方法,可将数据存到文件中。
这个方法接收两个参数:

  • 第一个参数:文件名。(不可以包含路径,都默认存储到/data/data/<package name/files/)
  • 第二个参数:文件的操作模式。有两种。
    • MODE_PRIVATE:默认操作模式,指定同名文件会覆盖源文件内容。
    • MODE_APPEND:如果文件存在,则往文件末尾追加内容。不存在同名文件则创建新文件。

openFileOutput()返回一个FileOutputStream对象,得到该对象可以使用Java流的方式将数据写入到文件中了。

public void save(){String data="Data to save";FileOutputStream out=null;BufferedWriter writer=null;try{out=openFileOutput("data", Context.MODE_PRIVATE);writer=new BufferedWriter(new OutputStreamWriter(out));}catch (IOException e){e.printStackTrace();}finally {try {if(writer!=null){writer.close();}} catch (IOException e){e.printStackTrace();}}}

从文件中读取数据

public class MainActivity extends AppCompatActivity {private EditText edit;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});edit=(EditText) findViewById(R.id.edit);String inputText=load();if(!TextUtils.isEmpty(inputText)){edit.setText(inputText);edit.setSelection(inputText.length());Toast.makeText(this,"Restoring succeeded ",Toast.LENGTH_SHORT).show();}}public void save(String inputText){String data="Data to save";FileOutputStream out=null;BufferedWriter writer=null;try{out=openFileOutput("data", Context.MODE_PRIVATE);writer=new BufferedWriter(new OutputStreamWriter(out));writer.write(inputText);}catch (IOException e){e.printStackTrace();}finally {try {if(writer!=null){writer.close();}} catch (IOException e){e.printStackTrace();}}}public void onDestroy(){super.onDestroy();String inputText=edit.getText().toString();save(inputText);}public String load(){FileInputStream in=null;BufferedReader read=null;StringBuilder content=new StringBuilder();try{in=openFileInput("data");read=new BufferedReader(new InputStreamReader(in));String line="";while((line =read.readLine())!=null){content.append(line);}}catch (IOException e){e.printStackTrace();}finally {try {if(read!=null){read.close();}} catch (IOException e){e.printStackTrace();}}}
}

6.3 SharedPreferences存储

不同于文件的存储方式。这个是使用键值对的方式来存储数据的。保存一条数据的时候,需要给这条数据提供一个对应的键。这个存储方式支持多种不同的数据类型。如果存储的数据类型是整型,那么读取出来的数据也是整形。如果存储的数据是字符串,那么读取出来的数据也是一个字符串。

6.3.1 将数据存储到是SharedPreferences中

如果要想使用SharedPreferences,所以先要获取到SharedPreferences对象。安卓一共的三种方法用来得到是SharedPreferences对象。

  1. Context类中的getSharedPreferences()方法。
    此方法接收两个参数,第一个参数用于指定这个文件的名称,如果指定的文件不存在,则会创建一个新的,SharedPreferences文件都是存放在/data/data/<package name /<shared_prefs目录下。
    第二个参数用于指定操作模式,目前只有MODE_PRIVATE一种模式可选,它是默认的操作模式。和直接传入0的效果是相同的,只有当前的应用程序才可以对这个SharedPreferences文件进行读写。其他几种操作模式均已被废弃。
  2. Activity类中的getPreferences()方法。
    这个方法和第一个Context类中的getSharedPreferences()方法很相似,不过这个方法只接受一个参数。使用这个方法会自动将当前活动的类名作为SharedPreferences文件名。
  3. PreferenceManager类的getDefaultSharedPreferences()方法
    是一个静态的方法,它接自动使用当前应用程序的包名作为前缀来命名这个SharedPreferences文件。得到了这个SharedPreferences对象之后就开始向这个文件中存储数据了。主要分为以下三个步骤实现:
    第一步,要用这个SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象。
    第二步,向这个SharedPreferences.Editor对象中添加数据,比如添加一个布尔型就用这个putBoolean()方法。添加一个字符串,则使用putString()方法,以此类推。
    第三步,用apply()方法将添加的数据提交,从而完成数据存储。
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});Button saveData=(Button) findViewById(R.id.save_data);saveData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();editor.putString("name","Tom");editor.putBoolean("married",false);editor.putInt("age",28);editor.apply();}});}
}

6.3.2 从SharedPreferences中读取数据

每一种get方法都对应了一种put的方法。

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});Button saveData=(Button) findViewById(R.id.save_data);saveData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();editor.putString("name","Tom");editor.putBoolean("married",false);editor.putInt("age",28);editor.apply();}});Button restoreData=(Button) findViewById(R.id.restore_data);restoreData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SharedPreferences pref=getSharedPreferences("data",MODE_PRIVATE);String name=pref.getString("name","");int age=pref.getInt("age",0);boolean married=pref.getBoolean("married",false);}});}
}

6.3.3 实现记住密码功能

activity_login.xmll

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textSize="18sp"android:text="Account"/><EditTextandroid:id="@+id/account"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="center_vertical"/></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textSize="18sp"android:text="Password:"/><EditTextandroid:id="@+id/password"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="center_vertical"android:inputType="textPassword"/></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><CheckBoxandroid:id="@+id/remember_pass"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:textSize="18sp"android:text="Remeber password"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout><Buttonandroid:id="@+id/login"android:layout_width="match_parent"android:layout_height="60dp"android:text="Login"/>
</LinearLayout>

LoginActivity.java

package com.example.broadcastbestpractice;import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;import java.util.prefs.PreferenceChangeEvent;public class LoginActivity extends BaseActivity{private EditText accountEdit;private EditText passwordEdit;private Button login;private SharedPreferences pref;private SharedPreferences.Editor editor;private CheckBox rememberPass;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);pref = PreferenceManager.getDefaultSharedPreferences(this);rememberPass=(CheckBox)findViewById(R.id.remember_pass);boolean isRemeber=pref.getBoolean("remember_password",false);if(isRemeber){//将账号和密码都设置到文本框String account=pref.getString("account","");String password=pref.getString("password","");accountEdit.setText(account);passwordEdit.setText(password);rememberPass.setChecked(true);}accountEdit=(EditText) findViewById(R.id.account);passwordEdit=(EditText) findViewById(R.id.password);login=(Button) findViewById(R.id.login);login.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String account=accountEdit.getText().toString();String password=passwordEdit.getText().toString();if(account.equals("admin")&&password.equals("123")){editor=pref.edit();//如果复选框被选中if(rememberPass.isChecked()){editor.putBoolean("remember_pass",false);editor.putString("account",account);editor.putString("password",password);}else{editor.clear();}editor.apply();Intent intent=new Intent(LoginActivity.this,MainActivity.class);startActivity(intent);finish();}else{Toast.makeText(LoginActivity.this,"account or password id invalid",Toast.LENGTH_SHORT).show();}}});}
}

6.4 SQLite数据库存储

这是一款轻量级的关系型数据库,它的运算速度非常快,但资源很少,通常只需要几百kb的内存就足够了,因此特别适合在移动设备上使用。SQLite不仅支持标准的SQL语,还遵循数据库的acid事务。

6.4.1 创建数据库

安卓为了让我们能够更加方便的管理数据库,专门提供了一个SQLiteOpenHelper主类。借助这个类就可以非常简单的对数据库进行创建和升级。

  • SQLiteOpenHelper这一个抽象类,如果要使用这个类的话,就需要创建一个自己的帮助类去继承它。

  • SQLiteOpenHelper有两个抽象方法。一个是onCreate(),一个是onupgrade()。需在自己的帮助类里面重写这两个方法。分别在这两个方法中去实现创造和升级数据库的逻辑。

  • SQLiteOpenHelper还有两个非常重要的实例方法。一个是getReadableDatabase(),另一个是getWritableDatabase()。两个方法都可以创建或者打开一个现有的数据库,如果数据库已经存在则打开,否则创建一个新的数据库。并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候,比如磁盘空间已满。getReadableDatabase()方法返回的对象将以只读的方式去带数据。getWritableDatabase()方法则将出现异常。

  • 有两个构造方法可以重写,一般使用参数少一点的那个构造方法即可。是构造函数方法中接收四个参数,第一个参数是context,必须有这个才能对数据库进行操作。第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。第三个参数允许我们在查询数据的时候返回一个自定义的Cursor游标,一般都是传入nulll。第四个参数,表示当前数据库的版本号,可用于对数据库进行升级操作。构建出的实例之后再调用它的getReadableDatabase()或者getWritableDatabase()方法就能够创建数据库。数据库的文件存放在/data/data/<package name/databases/目录下,此时重写的onCreate的方法也会执行。所以通常会在这里去处理一些创建表的逻辑。

public class MainActivity extends AppCompatActivity {private MyDatabaseHelper dbHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});dbHelper=new MyDatabaseHelper(this,"BookStroe.db",null,1);Button createDatabase=(Button) findViewById(R.id.creat_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dbHelper.getWritableDatabase();}});}
}
public class MyDatabaseHelper extends SQLiteOpenHelper {public final String CREATE_BOOK ="create table book ("+ "id integer primary key autoincrement, "+ "author text,"+ "price real,"+"pages integer,"+"name text)" ;private Context mContext;public MyDatabaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){super(context,name,factory,version);mContext=context;}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}

6.4.2 升级数据库

再加一个数据库表,记录图书的分类。

public class MyDatabaseHelper extends SQLiteOpenHelper {public final String CREATE_BOOK ="create table book ("+"id integer primary key autoincrement, "+"author text,"+"price real,"+"pages integer,"+"name text)" ;public final String CREATE_CATEGORY ="create table Category ("+"id integer primary key autoincrement, "+"category_name text,"+"category_code integer)";private Context mContext;public MyDatabaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){super(context,name,factory,version);mContext=context;}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);db.execSQL(CREATE_CATEGORY);Toast.makeText(mContext,"Create 成功",Toast.LENGTH_SHORT).show();}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}

看上去挺对的,现在运行一下程序,点击Create database按钮,没有弹出"Create 成功"的提示。
没有创建成功的原因是因为之前的bookstore数据库已经存在了,不管怎样点Create database按钮,这个oncreate方法中都不会再次执行,因此新添加的表就无法得到。
解决方法有两种。一种是卸载程序重新运行。另一种方法是在升级功能函数里面加下面几行代码。

    @Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL("drop table if exists Book");db.execSQL("drop table if exists Category");onCreate(db);}

如何让这个onUpgrage的方法能够执行?SQLiteOpenHelper的构造方法接收四个参数,最后一个参数是版本号,版本号默认传入是1,只要传入一个比1大的数就可以让onUpgrade的方法执行。
。。。
dbHelper=new MyDatabaseHelper(this,“BookStroe.db”,null,2);
Button createDatabase=(Button) findViewById(R.id.creat_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
。。。

6.4.3 添加数据

Button addData=(Button) findViewById(R.id.addData);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SQLiteDatabase db=dbHelper.getWritableDatabase();ContentValues values=new ContentValues();values.put("name","The Da vinci Code");values.put("pages",454);db.insert("Book",null,values);values.clear();values.put("name","the lost Symbol");values.put("pages",349);db.insert("Book",null,values);}});

6.4.4 更新数据

找到书名为The Davinci Code的一组数据,将这本书的价格改为17.52

Button updateData=(Button) findViewById(R.id.updateData);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SQLiteDatabase db=dbHelper.getWritableDatabase();ContentValues values=new ContentValues();values.put("price",17.52);db.update("Book",values,"name=?",new String[]{"The Davinci Code"});}});

6.4.5 删除数据

删除页数超过500页的书

 Button deleteData=(Button) findViewById(R.id.deleteData);deleteData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SQLiteDatabase db=dbHelper.getWritableDatabase();ContentValues values=new ContentValues();db.delete("Book","pages>?",new String[]{"500"});}});

6.4.6 查询数据

Button queryData=(Button) findViewById(R.id.queryData);queryData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SQLiteDatabase db=dbHelper.getWritableDatabase();Cursor cursor=db.query("Book",null,null,null,null,null,null);if(cursor.moveToFirst()){do{@SuppressLint("Range") String name=cursor.getString(cursor.getColumnIndex("name"));@SuppressLint("Range") int pages=cursor.getInt(cursor.getColumnIndex("pages"));}while(cursor.moveToNext());}cursor.close();}});

6.4.7 使用SQL操作数据库

直接使用SQL来完成增删改查。
添加数据
db.execSQL(“insert into Book (name,author,pages,price) values(?,?,?,?)”,new String[]{“The Da Vinci Code”,"Dan ",“454”,“16.35”} );

查询数据
db.rawQuery(“select * from Book”,null);

6.5 使用LitePal操作数据库

6.5.1 LitePal简介

是一个开源的Android数据库框架。采用了对象关系映射(ORM)的模式,并将我们平时开发最常用的一些数据库功能进行了封装。不用编写SQL就完成增删改查。

6.5.2 配置LitePal

怎样才能在项目中使用开源库?过去的方式比较复杂,下载开源库的jar包或者源码,然后再集成到项目中。现在简单多了,大多数的开源项目都会将版本提交到jcenter上,需要在app/build.gradle文件中声明该开源库的引用就可以了。

后续更新…

6.5.3 创建和升级数据库

6.5.4 增加

6.5.5 更新

6.5.6 删除

6.5.6 查询

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

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

相关文章

【白话机器学习系列】白话特征向量

白话特征向量 一个方阵 A A A 与列向量 v v v 的乘积会生成一个新的列向量。这个新向量通常与原向量有着不同的方向&#xff0c;矩阵在这里代表一个线性变换。然而&#xff0c;某些向量会保持其原始方向。我们称这种向量为矩阵 A A A 的特征向量&#xff08;eigenvector&…

03_led_horse_run_v1 跑马灯

03_led_horse_run_v1 在Verilog中实现跑马灯通常涉及到使用一个计数器来控制LED灯的亮灭顺序。 跑马灯是一种常见的电子显示方式&#xff0c;它通过控制多个LED灯的顺序点亮&#xff0c;形成一种动态的视觉效果&#xff0c;看起来就像灯在“跑”一样。 更新 使用dip开关控制…

一键 input 苹果 OpenELM,零门槛 Llama 3 教程,40+ 优质模型/数据集/教程,建议收藏!...

现在 AI 行业什么最火&#xff1f; 「大模型」一定仍然排在前三甲的位置。 自从 2022 年底 ChatGPT 面世以来&#xff0c;大模型在各行各业已经带来了太多的惊喜&#xff0c;应用场景愈发丰富&#xff0c;同时也带动了相关底层技术的普及与普适化。尤其是在开源模型繁荣发展之下…

描述Nacos中服务发现的流程。

Nacos中服务发现的流程解析 在微服务的架构体系中&#xff0c;服务发现是一个至关重要的组成部分。它解决了服务提供者和消费者之间如何动态发现对方地址的问题&#xff0c;使得微服务之间的调用更加灵活和高效。在众多服务发现组件中&#xff0c;Nacos以其易用性、高性能和丰…

C#核心之面向对象-多态

面向对象-多态 文章目录 1、Vob1、多态的概念2、多态的实现 2、抽象类和抽象方法1、抽象类2、抽象方法 3、接口1、接口的概念2、接口的声明3、接口的使用4、接口可以继承接口5、显示实现接口总结思考 电脑使用USB接口读取数据 4、密封方法 1、Vob 1、多态的概念 多态&#xf…

本周10个Github有趣项目WebLlama等

10个Github有趣的项目、工具和库 1、WebLlama Llama-3 网络Web代理&#xff0c;这是使用 Llama 3 构建的最强大的代理&#xff0c;通过聊天对话实现Web导航&#xff0c;可以按照说明浏览网页并与您交谈。 在Llama-3-8B-Web性能上超过了 GPT-4V&#xff08;*零样本&#xff09;…

为什么选择OpenNJet?OpenNJet下一代云原生应用引擎!OpenNJet开发实战!

前言导读 在当今这个数字化转型加速的时代&#xff0c;云原生技术已成为企业和开发者构建现代应用的首选路径。OpenNJet作为新一代云原生应用引擎&#xff0c;在国内外技术社区受到了广泛关注。 本文将深入探讨OpenNJet的特点、优势以及在开发实践中的应用&#xff0c;带您全…

【YoloDeployCsharp】基于.NET Framework的YOLO深度学习模型部署测试平台-源码下载与项目配置

基于.NET Framework 4.8 开发的深度学习模型部署测试平台,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等应用场景,同时支持图像与视频检测。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runtime以及OpenCV DNN,支持CPU、IGP…

用python画一个正八边形

1 问题 使用turtle库的turtle.fd()函数和turtle.seth()函数绘制一个边长100的正八边形。 2 方法 1、利用for循环解决如何画出图形中相同的八条边的问题。 2、再利用turtle.fd()函数和turtle.seth()函数画出完整的图形。 代码清单 1 import turtleturtle.pensize(2)d0for i in r…

【系统架构师】-选择题(十三)

1、在某企业的营销管理系统设计阶段&#xff0c;属性"员工"在考勤管理子系统中被称为"员工"&#xff0c;而在档案管理子系统中被称为"职工"&#xff0c;这类冲突称为&#xff08; 命名冲突&#xff09;。 同一个实体在同系统中存在不同的命名&am…

智慧旅游引领未来风尚,科技助力旅行更精彩:科技的力量推动旅游业创新发展,为旅行者带来更加便捷、高效和智能的旅行服务

目录 一、引言 二、智慧旅游的概念与特点 &#xff08;一&#xff09;智慧旅游的概念 &#xff08;二&#xff09;智慧旅游的特点 三、科技推动旅游业创新发展 &#xff08;一&#xff09;大数据技术的应用 &#xff08;二&#xff09;人工智能技术的应用 &#xff08;…

推荐收藏!40 道算法工程师必问的高频面试题!

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#xff1a…

【计算机科学速成课】笔记二

笔记一 文章目录 7.CPU阶段一&#xff1a;取指令阶段阶段二&#xff1a;解码阶段阶段三&#xff1a;执行阶段 8.指令和程序9.高级CPU设计——流水线与缓存10.早期编程方式11.编程语言发展史12.编程原理13.算法入门14.数据结构15.阿兰图灵 7.CPU CPU也叫中央处理器&#xff0c;…

在R的 RGui中,使用devtools 安装trajeR

创建于&#xff1a;2024.5.5 文章目录 1. 报错信息2. 尝试使用指定的清华镜像&#xff0c;没有解决3. 找到原因&#xff1a;官网把包删除了4. 尝试从网上下载&#xff0c;然后安装。没有成功5. 使用devtools安装5.1 尝试直接安装&#xff1a;install.packages("devtools&q…

写点简单的算法压压惊

题目 问题描述 小蓝是个直男&#xff0c;他老是不懂女朋友的心思&#xff0c;甚至不知道女朋友 有没有生气。 后来他逐渐发现&#xff0c;如果女朋友给他发的消息的字符个数小于等 于 10 个&#xff0c;那么就是生气了&#xff0c;否则就是没有生气。 现在收到一条女朋友发来的…

关于YOLO8学习(四)模型转换为ncnn

前文 关于YOLO8学习(一)环境搭建,官方检测模型部署到手机 关于YOLO8学习(二)数据集收集,处理 关于YOLO8学习(三)训练自定义的数据集 简介 本文将会讲解: (1)如何通过PyCharm,进行pt模型的转换,最后输出一个适合手机端使用的模型 开发环境 win10、python 3.11…

C语言写一个终端进度条

C语言写一个终端进度条 这个功能挺简单的&#xff0c;主要有以下两点&#xff1a; 如何获取终端宽度如何让字符在原地闪烁 如何获取终端宽度 这里用到了设备控制接口函数ioctl()&#xff0c;下面简单的介绍一下这个函数的用法&#xff1a; ioctl是一个在Unix和类Unix系统中…

1-36 双列集合

一 Map集合 1.存储特点(重点记忆:) 以键值对(KEY-VALUE)形式存储 2.特点: ①将键值对看做对象进行存储 ②KEY 不能重复,VALUE可以重复 ③每一对K-V都是意义对应的映射关系 3.拓展:Map集合是双列集合,由两个单列集合组成的 分析KEY和VALUE所在的是什么种类集合 ①KEY不…

JS基础:js的2种基本用法,4个属性详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

C++容器map及unordered_map底层实现和性能上有所不同

std::map 和 std::unordered_map 都是 C 标准库中用于实现关联容器的类模板&#xff0c;但它们在底层实现和性能上有所不同。 1. std::map&#xff1a; - 使用红黑树实现&#xff0c;保持元素的有序性。因此&#xff0c;所有操作的时间复杂度都是 O(log n)&#xff0c;其中…