其实这些微软docs都有现成的,但是现在的人想对浮躁些,去看的不会太多,所以这里就再记录下 ,大家一起懒一起浮躁,呵呵.

0.基础知识

通过减少生成内容所需的工作,缓存可以显著提高应用的性能和可伸缩性。 缓存对不经常更改的数据效果最佳。 缓存生成的数据副本的返回速度可以比从原始源返回更快。 在编写并测试应用时,应避免依赖缓存的数据。ASP.NET Core 支持多种不同的缓存。 最简单的缓存基于 IMemoryCache,它表示存储在 Web 服务器内存中的缓存。 在包含多个服务器的服务器场上运行的应用应确保在使用内存中缓存时,会话是粘性的。 粘性会话可确保来自客户端的后续请求都转到同一台服务器。 例如,Azure Web 应用使用应用程序请求路由(ARR) 将所有的后续请求路由到同一台服务器。Web 场中的非粘性会话需要分布式缓存以避免缓存一致性问题。 对于某些应用,分布式的缓存可以支持更高版本向外缩放比内存中缓存。 使用分布式缓存可将缓存内存卸载到外部进程。内存中缓存可以存储任何对象;分布式缓存接口仅限于byte[]

这里只说有这么几种方式,但是不去深入.不喜拉到.

1.常见缓存响应的四种方式

1.1.内存缓存

  顾名思义,缓存在内存中,生命周期默认伴随应用程序

1.2.响应缓存

  响应缓存可减少客户端或代理到 web 服务器发出的请求数。 响应缓存还减少了工作的 web 服务器执行以生成响应。 响应缓存控制标头,指定要如何客户端、 代理和响应缓存中间件。

1.3.响应缓存中间件

  Microsoft.AspNetCore.ResponseCaching 包中的ResponseCaching

1.4.分布式缓存

  就是你对象,她会霸道的和你说和别人说,你是他的....但是到最后到底谁会不是是谁的谁 谁也不知道,但是她有对你的使用权,逛街包要挂在你身上,取东西要从你身上的包里拿出来.

其中的1-3点都是对core本身开刀的手术,4点是不仅对自己动刀子,还要对别人家(服务)动刀子...嗯,比较坏.

1.1内存缓存

  内存缓存即我们常用的System.Runtime.Caching/MemoryCache.有关缓存方法的说明,请参阅IMemoryCache 方法CacheExtensions 方法 .

  对象    : IMemoryCache

  可选配置项: MemoryCacheEntryOptions

      • 设置绝对到期时间。 这是条目可以被缓存的最长时间,防止可调过期持续更新时该条目过时太多。
      • 设置可调过期时间。 访问此缓存项的请求将重置可调过期时钟。
      • 缓存优先级设置为CacheItemPriority.NeverRemove
      • 设置一个PostEvictionDelegate它将在条目从缓存中清除后调用。 在代码中运行该回调的线程不同于从缓存中移除条目的线程。

  在core中我们使用内存缓存只需要注入 IMemoryCache 即可,然后就是一股脑地 get,getString, set....一顿操作猛如虎;具体案例见官方提供的参考.

1.2响应缓存

  a)  HTTP 1.1 缓存的缓存控制标头的规范需要接受是有效的缓存Cache-Control客户端发送的标头。 客户端可以发出请求的no-cache标头值和强制服务器生成的每个请求的新响应。始终遵循客户端Cache-Control请求标头是有意义,如果您考虑 HTTP 缓存的目标。 在正式规范,缓存旨在减少的满足请求的客户端、 代理和服务器的网络延迟和网络开销。 它不一定是一种方法来控制源服务器上的负载。没有任何当前开发人员可以控制此缓存的行为使用时响应缓存中间件因为中间件遵循正式缓存规范。 未来的增强功能到中间件将允许配置中间件,若要忽略的请求Cache-Control标头决定用于缓存的响应时。 使用中间件时,这将为您提供更好地控制负载在服务器上的机会。

  b) ResponseCacheAttribute指定缓存响应中设置相应的标头所需的参数。ResponseCache特性可应用于操作 (方法) 和控制器 (类)。 方法级属性重写在类级别特性中指定的设置。

1.3响应缓存中间件

  引用Microsoft.AspNetCore.App 元包或添加到的包引用Microsoft.AspNetCore.ResponseCaching包。

  配置:

  在Startup.ConfigureServices,将中间件添加到服务集合。

  services.AddResponseCaching();

  将应用配置为使用与中间件UseResponseCaching扩展方法,它将中间件添加到请求处理管道。 该示例应用将添加Cache-Control缓存最多 10 秒的可缓存响应的响应标头。 该示例将发送Vary标头用于配置中间件来提供缓存的响应才Accept-Encoding后续请求标头匹配的原始请求。 中的代码示例中, CacheControlHeaderValueHeaderNames需要using语句Microsoft.Net.Http.Headers命名空间。

  在startUp.cs的 Configure中

  app.UseResponseCaching();

   app.Use(async (context, next) => {

      // For GetTypedHeaders, add: using Microsoft.AspNetCore.Http;

    context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue() {Public = true, MaxAge = TimeSpan.FromSeconds(10) };

    context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = new string[] { "Accept-Encoding" };

    await next();

    });

  app.UseMvc();

 选项:

  中间件提供了三个选项用于控制响应缓存。

选项 描述
UseCaseSensitivePaths 确定是否在区分大小写的路径上会缓存响应。 默认值为 false
MaximumBodySize 以字节为单位的响应正文最大缓存大小。 默认值是64 * 1024 * 1024(64 MB)。
大小限制 以字节为单位的响应缓存中间件大小限制。 默认值是100 * 1024 * 1024(100 MB)。

下面的示例配置到中间件:

    • 小于或等于 1024 字节的缓存响应。
    • 将响应存储通过区分大小写的路径 (例如,/page1/Page1单独存储)。
  services.AddResponseCaching(options =>
  {
  options.UseCaseSensitivePaths = true;
  options.MaximumBodySize = 1024;
  });

VaryByQueryKeys:

在使用 MVC/Web API 控制器或 Razor 页面页模型ResponseCache属性指定设置适当的标头为响应缓存所需的参数。 唯一参数ResponseCache严格需要中间件的属性是VaryByQueryKeys,这并不对应于实际的 HTTP 标头。 有关详细信息,请参阅ResponseCache 属性

不使用时ResponseCache属性中,响应缓存可以与变化VaryByQueryKeys功能。 使用ResponseCachingFeature直接从IFeatureCollectionHttpContext:

 var responseCachingFeature = context.HttpContext.Features.Get<IResponseCachingFeature>();
if (responseCachingFeature != null){
      responseCachingFeature.VaryByQueryKeys = new[] { "MyKey" };
  }

使用单个值等于*VaryByQueryKeys随缓存所有请求查询参数而都变化。

   响应缓存中间件所使用的 HTTP 标头

  用 HTTP 标头配置中间件的响应缓存。

  

  

1.4分布式缓存  

  上面的不是什么重点,小项目用用玩不是问题,所以没太大意思,重点是这里的分布式缓存实现.

  分布式的缓存是由多个应用程序服务器,通常作为对其进行访问的应用程序服务器的外部服务维护共享缓存。 分布式的缓存可以提高性能和可伸缩性的 ASP.NET Core 应用,尤其是当应用程序托管的云服务或服务器场。

  分布式的缓存具有几大优势,其中缓存的数据存储在单个应用程序服务器其他缓存方案。

  当分布式缓存的数据,则数据:

  • 是连贯(一致) 跨多个服务器的请求。
  • 服务器重新启动和应用部署仍然有效。
  • 不使用本地内存。

    分布式的缓存配置是特定于实现的。 本文介绍如何配置 SQL Server 和 Redis 分布式的缓存。 第三方实现也是可用,如NCache(GitHub 上的 NCache)。 无论选择哪一种实现,该应用程序与使用缓存进行交互IDistributedCache接口。

  系统必备

  若要使用的 SQL Server 分布式缓存,引用Microsoft.AspNetCore.App 元包或添加到的包引用Microsoft.Extensions.Caching.SqlServer包。

  若要使用 Redis 分布式缓存,引用Microsoft.AspNetCore.App 元包并添加到的包引用Microsoft.Extensions.Caching.Redis包。 Redis 包不包括在Microsoft.AspNetCore.App包,因此您必须在项目文件中分别引用 Redis 包。

   IDistributedCache 接口

IDistributedCache接口提供了以下方法操作的分布式的缓存实现中的项:

  • GetGetAsync –接受字符串键和检索缓存的项作为byte[]数组如果在缓存中找到。
  • SetSetAsync –中添加项 (作为byte[]数组) 到使用字符串键的缓存。
  • RefreshRefreshAsync –刷新缓存基于其密钥,重置其滑动到期超时值 (如果有) 中的项。
  • RemoveRemoveAsync –移除缓存项根据其字符串键值。

  建立分布式缓存服务

  注册的实现IDistributedCacheStartup.ConfigureServices。 本主题中所述的框架提供实现包括:

  分布式的内存缓存

  分布式内存缓存 (AddDistributedMemoryCache) 是框架提供的实现IDistributedCache,在内存中存储项。 分布式内存缓存不是实际的分布式的缓存。 缓存的项存储在运行该应用程序的服务器上的应用程序实例。

  分布式内存缓存是一个有用的实现:

  • 在开发和测试方案。
  • 生产和内存消耗情况中使用一台服务器时不会产生问题。 实现分布式内存缓存摘要缓存数据存储。 它允许实现真正的分布式缓存解决方案在将来如果多个节点或容错能力变得非常必要。

  示例应用将在开发环境中运行应用时使用的分布式内存缓存:

public void ConfigureServices(IServiceCollection services)
{ if (_hostContext.IsDevelopment()){ services.AddDistributedMemoryCache();}
   else
   {
      services.AddDistributedSqlServerCache(options =>
      {
        options.ConnectionString = _config["DistCache_ConnectionString"];
        options.SchemaName = "dbo";
        options.TableName = "TestCache";
       });
     }
   }
}

  1.4.1.分布式的 SQL 服务器缓存

  SQL Server 的分布式缓存实现 (AddDistributedSqlServerCache) 允许使用 SQL Server 数据库作为其后备存储分布式的缓存。 若要在 SQL Server 实例中创建的 SQL Server 缓存的项表中,可以使用sql-cache工具。 该工具使用名称和指定的架构创建一个表。通过运行 SQL Server 中创建一个表sql-cache create命令。 提供 SQL Server 实例 (Data Source),数据库 (Initial Catalog),架构 (例如, dbo),以及表名 (例如, TestCache):

  dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

  记录一条消息以指示该工具已成功:

   Table and index were created successfully.

   创建的表sql-cache工具具有以下架构:

 备注

  应用应操作使用的实例的缓存值IDistributedCache,而不SqlServerCache

  本示例应用实现SqlServerCache非开发环境中:

public void ConfigureServices(IServiceCollection services)
{
if (_hostContext.IsDevelopment())
{
services.AddDistributedMemoryCache();
}
else
{
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString =
_config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
}

备注

  一个ConnectionString(和 (可选)SchemaNameTableName) 通常存储在源代码管理之外 (例如,通过存储机密管理器中或在appsettings.json /appsettings。{Environment}.json文件)。 连接字符串可能包含应从源代码管理系统的凭据。

  1.4.2.分布式的 Redis 缓存

Redis是一种开源的内存中数据存储,通常用作分布式缓存。 您可以使用 Redis 本地,并且您可以配置Azure Redis 缓存Azure 托管 ASP.NET Core 应用。 应用配置缓存实现使用RedisCache实例 (AddDistributedRedisCache):

services.AddDistributedRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});

  若要在本地计算机上安装 Redis:

  使用分布式的缓存

  若要使用IDistributedCache接口,请求的实例IDistributedCache从任何应用程序中的构造函数。 实例由提供依赖关系注入 (DI)。当应用启动时IDistributedCache注入到Startup.Configure。 使用缓存的当前时间IApplicationLifetime(有关详细信息,请参阅Web 主机: IApplicationLifetime 接口):

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime, IDistributedCache cache)
{
lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds());
cache.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});

  示例应用程序注入IDistributedCacheIndexModel以供索引页。

  每次加载索引页时,缓存时间检查缓存OnGetAsync。 如果尚未过期的缓存的时间,将显示时间。 如果自上一次访问缓存的时间 (已加载此页的最后一个时间) 已过去 20 秒,该页将显示缓存时间已过

  通过选择,立即更新为当前时间的缓存的时间重置缓存时间按钮。 按钮触发器OnPostResetCachedTime处理程序方法。

public class IndexModel : PageModel
{
private readonly IDistributedCache _cache; public IndexModel(IDistributedCache cache)
{
_cache = cache;
} public string CachedTimeUTC { get; set; } public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC"); if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
} public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds());
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options); return RedirectToPage();
}
}

    备注

  无需为IDistributedCache实例使用 Singleton 或 Scoped 生命周期(至少对内置实现来说是这样的)。

  此外可以创建IDistributedCache实例可能需要某一个而不是使用 DI,但在代码中创建实例会使代码难以测试和违反显式依赖关系原则

  建议

  确定哪一种实现的时IDistributedCache最适合于您的应用程序,请考虑以下:

  • 现有的基础结构
  • 性能要求
  • 成本
  • 团队体验

  缓存解决方案通常依赖于内存中存储提供快速检索的缓存数据,但内存是有限的资源,而且成本展开。 仅存储通常用于缓存中的数据。通常情况下,Redis 缓存提供更高的吞吐量和延迟低于 SQL Server 缓存。 但是,进行基准测试时通常需要确定的缓存策略的性能特征。当 SQL Server 用作分布式的缓存后备存储时,使用的同一个数据库缓存与应用程序的普通数据存储和检索可以对这两者的性能产生负面影响。 我们建议使用专用的 SQL Server 实例为分布式缓存后备存储。

2.IDistributedCache简单封装

/// <summary>
/// <see cref="IDistributedCache"/>扩展方法
/// </summary>
public static class DistributedCacheExtensions
{
/// <summary>
/// 将对象存入缓存中
/// </summary>
public static void SetCache(this IDistributedCache cache, string key, object value, DistributedCacheEntryOptions options = null)
{
string json = JsonConvert.SerializeObject(value);
if (options == null)
{
cache.SetString(key, json);
}
else
{
cache.SetString(key, json, options);
}
} /// <summary>
/// 异步将对象存入缓存中
/// </summary>
public static async Task SetCacheAsync(this IDistributedCache cache, string key, object value, DistributedCacheEntryOptions options = null)
{
string json = JsonConvert.SerializeObject(value);
if (options == null)
{
await cache.SetStringAsync(key, json);
}
else
{
await cache.SetStringAsync(key, json, options);
}
} /// <summary>
/// 将对象存入缓存中,使用指定时长
/// </summary>
public static void Set(this IDistributedCache cache, string key, object value, int cacheSeconds)
{
DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
options.SetAbsoluteExpiration(TimeSpan.FromSeconds(cacheSeconds));
cache.SetCache(key, value, options);
} /// <summary>
/// 异步将对象存入缓存中,使用指定时长
/// </summary>
public static Task SetAsync(this IDistributedCache cache, string key, object value, int cacheSeconds)
{
DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
options.SetAbsoluteExpiration(TimeSpan.FromSeconds(cacheSeconds));
return cache.SetCacheAsync(key, value, options);
} /// <summary>
/// 将对象存入缓存中,使用功能配置
/// </summary>
public static void Set(this IDistributedCache cache, string key, object value, DistributedCacheEntryOptions cacheOptions)
{
if (cacheOptions == null)
{
return;
}
cache.SetCache(key, value, cacheOptions);
} /// <summary>
/// 异步将对象存入缓存中,使用功能配置
/// </summary>
public static Task SetAsync(this IDistributedCache cache, string key, object value, DistributedCacheEntryOptions cacheOptions)
{
if (cacheOptions == null)
{
return Task.FromResult();
}
return cache.SetCacheAsync(key, value, cacheOptions);
} /// <summary>
/// 获取指定键的缓存项
/// </summary>
public static TResult Get<TResult>(this IDistributedCache cache, string key)
{
string json = cache.GetString(key);
if (json == null)
{
return default(TResult);
}
return JsonConvert.DeserializeObject<TResult>(json);
} /// <summary>
/// 异步获取指定键的缓存项
/// </summary>
public static async Task<TResult> GetAsync<TResult>(this IDistributedCache cache, string key)
{
string json = await cache.GetStringAsync(key);
if (json == null)
{
return default(TResult);
}
return JsonConvert.DeserializeObject<TResult>(json);
} /// <summary>
/// 获取指定键的缓存项,不存在则从指定委托获取,并回存到缓存中再返回
/// </summary>
public static TResult GetCache<TResult>(this IDistributedCache cache, string key, Func<TResult> getFunc, DistributedCacheEntryOptions options = null)
{
TResult result = cache.Get<TResult>(key);
if (!Equals(result, default(TResult)))
{
return result;
}
result = getFunc();
if (Equals(result, default(TResult)))
{
return default(TResult);
}
cache.SetCache(key, result, options);
return result;
} /// <summary>
/// 异步获取指定键的缓存项,不存在则从指定委托获取,并回存到缓存中再返回
/// </summary>
public static async Task<TResult> GetCacheAsync<TResult>(this IDistributedCache cache, string key, Func<Task<TResult>> getAsyncFunc, DistributedCacheEntryOptions options = null)
{
TResult result = await cache.GetAsync<TResult>(key);
if (!Equals(result, default(TResult)))
{
return result;
}
result = await getAsyncFunc();
if (Equals(result, default(TResult)))
{
return default(TResult);
}
await cache.SetCacheAsync(key, result, options);
return result;
} /// <summary>
/// 获取指定键的缓存项,不存在则从指定委托获取,并回存到缓存中再返回
/// </summary>
public static TResult Get<TResult>(this IDistributedCache cache, string key, Func<TResult> getFunc, int cacheSeconds)
{
DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
options.SetAbsoluteExpiration(TimeSpan.FromSeconds(cacheSeconds));
return cache.GetCache<TResult>(key, getFunc, options);
} /// <summary>
/// 异步获取指定键的缓存项,不存在则从指定委托获取,并回存到缓存中再返回
/// </summary>
public static Task<TResult> GetAsync<TResult>(this IDistributedCache cache, string key, Func<Task<TResult>> getAsyncFunc, int cacheSeconds)
{
DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
options.SetAbsoluteExpiration(TimeSpan.FromSeconds(cacheSeconds));
return cache.GetAsync<TResult>(key, getAsyncFunc, options);
} /// <summary>
/// 获取指定键的缓存项,不存在则从指定委托获取,并回存到缓存中再返回
/// </summary>
public static TResult Get<TResult>(this IDistributedCache cache, string key, Func<TResult> getFunc, DistributedCacheEntryOptions cacheOptions)
{
if (cacheOptions == null)
{
return getFunc();
}
return cache.Get<TResult>(key, getFunc, cacheOptions);
} /// <summary>
/// 获取指定键的缓存项,不存在则从指定委托获取,并回存到缓存中再返回
/// </summary>
public static Task<TResult> GetAsync<TResult>(this IDistributedCache cache, string key, Func<Task<TResult>> getAsyncFunc, DistributedCacheEntryOptions cacheOptions)
{
if (cacheOptions == null)
{
return getAsyncFunc();
}
return cache.GetAsync<TResult>(key, getAsyncFunc, cacheOptions);
}
}

使用时候注入IDistributedCache即可,实现的效果和 内存缓存效果是一样的,.....还没看其实现源码,所以,,吹不起来.

这时候再上一篇中我们通过扫码登录之后获取到token,保存到 idistributedCache对象即可

.net core 2.x - 缓存的四种方式的更多相关文章

  1. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  2. C#_批量插入数据到Sqlserver中的四种方式

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  3. Dojo初探之2:设置dojoConfig详解,dojoConfig参数详解+Dojo中预置自定义AMD模块的四种方式(基于dojo1.11.2)

    Dojo中想要加载自定义的AMD模块,需要先设置好这个模块对应的路径,模块的路径就是这个模块的唯一标识符. 一.dojoConfig参数设置详解 var dojoConfig = { baseUrl: ...

  4. Spring事务管理的四种方式(以银行转账为例)

    Spring事务管理的四种方式(以银行转账为例) 一.事务的作用 将若干的数据库操作作为一个整体控制,一起成功或一起失败.   原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不 ...

  5. C#批量插入数据到Sqlserver中的四种方式 - 转

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  6. Java创建线程的四种方式

    Java创建线程的四种方式 1.继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容 创建Thread子类的实例,即创建了线程对象. ...

  7. C# 字符串拼接性能探索 c#中+、string.Concat、string.Format、StringBuilder.Append四种方式进行字符串拼接时的性能

    本文通过ANTS Memory Profiler工具探索c#中+.string.Concat.string.Format.StringBuilder.Append四种方式进行字符串拼接时的性能. 本文 ...

  8. 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】

    不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...

  9. ASP.NET MVC之下拉框绑定四种方式(十)

    前言 上两节我们讲了文件上传的问题,关于这个上传的问题还未结束,我也在花时间做做分割大文件处理以及显示进度的问题,到时完成的话再发表,为了不耽误学习MVC其他内容的计划,我们今天开始好好讲讲关于MVC ...

随机推荐

  1. 设置Debian8 光秃秃的桌面(图标,窗口样式等)

    在虚拟机里按抓了Debian8, 然后进入桌面后很不习惯,最主要是桌面光秃秃的, 今天终于不小心找到办法了: 按[Win]键, 找到"优化工具"程序; 或者是在右上角的[应用程序] ...

  2. bzoj1078【SCOI2008】斜堆

    题意: 斜堆(skew heap)是一种常用的数据结构.它也是二叉树,且满足与二叉堆相同的堆性质:每个非根结点的值都比它父亲大.因此在整棵斜堆中,根的值最小.但斜堆不必是平衡的,每个结点的左右儿子的大 ...

  3. 点击ViewGroup时其子控件也变成pressed状态的原因分析及解决办法

    这个问题,当初在分析touch事件处理的时候按理应该分析到的,可是由于我当时觉得这块代码和touch的主题不是那么紧密, 就这么忽略掉了,直到后来在这上面遇到了问题.其实这个现象做Android开发的 ...

  4. Google十大惊人产品

    国外资讯网站BusinessInsider刊文细数了谷歌惊世骇俗的十大产品,范围从无人驾驶汽车到太空电梯再到高空风力发电,每一项都令人无限神往,充满未来感. 以下是谷歌十大惊人产品: 众所周知,谷歌并 ...

  5. BZOJ 3142 数列(组合)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3142 题意:给出n,K,m,p.求有多少长度为K的序列A,满足:(1)首项为正整数:(2 ...

  6. ES6笔记② 箭头函数

    特性介绍 箭头函数是ES6新增的特性之一,它为JS这门语言提供了一种全新的书写函数的语法. //ES5 function fun(x,y){ return x+y; } console.log(fun ...

  7. 浅谈href=#与href=javascript:void(0)的区别

    #"包含了一个位置信息 默认的锚点是#top 也就是网页的上端 而javascript:void(0)  仅仅表示一个死链接 这就是为什么有的时候页面很长浏览链接明明是#可是跳动到了页首 而 ...

  8. CF CROC 2016 Intellectual Inquiry

    题目链接:http://codeforces.com/contest/655/problem/E 大意是Bessie只会英文字母表中的前k种字母,现在有一个长度为m+n的字母序列,Bessie已经知道 ...

  9. (PAT)L2-004 这是二叉搜索树吗?(数据结构)

    题目链接:https://www.patest.cn/contests/gplt/L2-004 一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的 ...

  10. Jrebel 配置

    先下载插件 http://139.199.89.239:1008/88414687-3b91-4286-89ba-2dc813b107ce http://jrebel.autoseasy.cn/xix ...