DocX学习系列

DocX开源WORD操作组件的学习系列一 :  http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.html

DocX开源WORD操作组件的学习系列二 :  http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_csharp_005_docx2.html

DocX开源WORD操作组件的学习系列三:  http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_csharp_006_docx3.html

DocX开源WORD操作组件的学习系列四:  http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_csharp_006_docx4.html

插入表格1低效

        static void LargeTable()
{
Console.WriteLine("\tLargeTable()");
var _directoryWithFiles = "docs\\";
using (var output = File.Open(_directoryWithFiles + "LargeTable.docx", FileMode.Create))
{
using (var doc = DocX.Create(output))
{
var tbl = doc.InsertTable(, ); var wholeWidth = doc.PageWidth - doc.MarginLeft - doc.MarginRight;
var colWidth = wholeWidth / tbl.ColumnCount;
var colWidths = new int[tbl.ColumnCount];
tbl.AutoFit = AutoFit.Contents;
var r = tbl.Rows[];
var cx = ;
foreach (var cell in r.Cells)
{
cell.Paragraphs.First().Append("Col " + cx);
//cell.Width = colWidth;
cell.MarginBottom = ;
cell.MarginLeft = ;
cell.MarginRight = ;
cell.MarginTop = ; cx++;
}
tbl.SetBorder(TableBorderType.Bottom, BlankBorder);
tbl.SetBorder(TableBorderType.Left, BlankBorder);
tbl.SetBorder(TableBorderType.Right, BlankBorder);
tbl.SetBorder(TableBorderType.Top, BlankBorder);
tbl.SetBorder(TableBorderType.InsideV, BlankBorder);
tbl.SetBorder(TableBorderType.InsideH, BlankBorder); doc.Save();
}
}
Console.WriteLine("\tCreated: docs\\LargeTable.docx\n");
} static void TableWithSpecifiedWidths()
{
Console.WriteLine("\tTableSpecifiedWidths()");
var _directoryWithFiles = "docs\\";
using (var output = File.Open(_directoryWithFiles + "TableSpecifiedWidths.docx", FileMode.Create))
{
using (var doc = DocX.Create(output))
{
var widths = new float[] { 200f, 100f, 300f };
var tbl = doc.InsertTable(, widths.Length);
tbl.SetWidths(widths);
var wholeWidth = doc.PageWidth - doc.MarginLeft - doc.MarginRight;
tbl.AutoFit = AutoFit.Contents;
var r = tbl.Rows[];
var cx = ;
foreach (var cell in r.Cells)
{
cell.Paragraphs.First().Append("Col " + cx);
//cell.Width = colWidth;
cell.MarginBottom = ;
cell.MarginLeft = ;
cell.MarginRight = ;
cell.MarginTop = ; cx++;
}
//add new rows
for (var x = ; x < ; x++)
{
r = tbl.InsertRow();
cx = ;
foreach (var cell in r.Cells)
{
cell.Paragraphs.First().Append("Col " + cx);
//cell.Width = colWidth;
cell.MarginBottom = ;
cell.MarginLeft = ;
cell.MarginRight = ;
cell.MarginTop = ; cx++;
}
}
tbl.SetBorder(TableBorderType.Bottom, BlankBorder);
tbl.SetBorder(TableBorderType.Left, BlankBorder);
tbl.SetBorder(TableBorderType.Right, BlankBorder);
tbl.SetBorder(TableBorderType.Top, BlankBorder);
tbl.SetBorder(TableBorderType.InsideV, BlankBorder);
tbl.SetBorder(TableBorderType.InsideH, BlankBorder); doc.Save();
}
}
Console.WriteLine("\tCreated: docs\\TableSpecifiedWidths.docx\n"); }

插入表格2高效

     public class Data
{
public string Name { get; set; }
public string AliasName { get; set; } }
private static void InsertTabelTest()
{
Console.WriteLine("\table1()");
//我这里生成一部分样例数据
var list = new List<Data>();
for (int i = ; i < ; i++)
{
list.Add(new Data() {Name = i.ToString(),AliasName = i+".."+i.ToString()});
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Restart();
//直接使用inserttable插入table
using (DocX document = DocX.Create(@"docs\InsertTable.docx"))
{ var table1= document.InsertTable(list.Count,);
table1.Design=TableDesign.ColorfulGrid;
for (int i = ; i < list.Count; i++)
{
table1.Rows[i].Cells[].Paragraphs.First().InsertText(list[i].Name);
table1.Rows[i].Cells[].Paragraphs.First().InsertText(list[i].AliasName);
}
document.Save(); Console.WriteLine("\tCreated: docs\\InsertTable.docx\n");
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds+"毫秒");// 234277.7521毫秒
stopwatch.Restart();
//使用addtable后再inserttable
using (DocX document = DocX.Create(@"docs\AddTable.docx"))
{ var table1 = document.AddTable(list.Count, );
table1.Design = TableDesign.ColorfulGrid;
for (int i = ; i < list.Count; i++)
{
table1.Rows[i].Cells[].Paragraphs.First().InsertText(list[i].Name);
table1.Rows[i].Cells[].Paragraphs.First().InsertText(list[i].AliasName);
}
document.InsertTable(table1);
document.Save();
Console.WriteLine("\tCreated: docs\\AddTable.docx\n");
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds +"毫秒");//60773.5141毫秒
Console.ReadKey(); ////////////////////////////////////////////////// }

文档加密

   static void ProtectedDocument()
{
Console.WriteLine("\tHelloWorldPasswordProtected()"); // Create a new document.
using (DocX document = DocX.Create(@"docs\HelloWorldPasswordProtected.docx"))
{
// Insert a Paragraph into this document.
Paragraph p = document.InsertParagraph(); // Append some text and add formatting.
p.Append("Hello World!^011Hello World!")
.Font(new Font("Times New Roman"))
.FontSize()
.Color(WindowsColor.Blue)
.Bold(); // Save this document to disk with different options
// Protected with password for Read Only
EditRestrictions erReadOnly = EditRestrictions.readOnly;
document.AddProtection(erReadOnly, "oracle");
document.SaveAs(@"docs\\HelloWorldPasswordProtectedReadOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldPasswordProtectedReadOnly.docx\n"); // Protected with password for Comments
EditRestrictions erComments = EditRestrictions.comments;
document.AddProtection(erComments, "oracle");
document.SaveAs(@"docs\\HelloWorldPasswordProtectedCommentsOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldPasswordProtectedCommentsOnly.docx\n"); // Protected with password for Forms
EditRestrictions erForms = EditRestrictions.forms;
document.AddProtection(erForms, "oracle");
document.SaveAs(@"docs\\HelloWorldPasswordProtectedFormsOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldPasswordProtectedFormsOnly.docx\n"); // Protected with password for Tracked Changes
EditRestrictions erTrackedChanges = EditRestrictions.trackedChanges;
document.AddProtection(erTrackedChanges, "oracle");
document.SaveAs(@"docs\\HelloWorldPasswordProtectedTrackedChangesOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldPasswordProtectedTrackedChangesOnly.docx\n"); // But it's also possible to add restrictions without protecting it with password. // Protected with password for Read Only
document.AddProtection(erReadOnly);
document.SaveAs(@"docs\\HelloWorldWithoutPasswordReadOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldWithoutPasswordReadOnly.docx\n"); // Protected with password for Comments
document.AddProtection(erComments);
document.SaveAs(@"docs\\HelloWorldWithoutPasswordCommentsOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldWithoutPasswordCommentsOnly.docx\n"); // Protected with password for Forms
document.AddProtection(erForms);
document.SaveAs(@"docs\\HelloWorldWithoutPasswordFormsOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldWithoutPasswordFormsOnly.docx\n"); // Protected with password for Tracked Changes
document.AddProtection(erTrackedChanges);
document.SaveAs(@"docs\\HelloWorldWithoutPasswordTrackedChangesOnly.docx");
Console.WriteLine("\tCreated: docs\\HelloWorldWithoutPasswordTrackedChangesOnly.docx\n");
}
}

缩进

  private static void Indentation()
{
Console.WriteLine("\tIndentation()"); // Create a new document.
using (DocX document = DocX.Create(@"docs\Indentation.docx"))
{
// Create a new Paragraph.
Paragraph p = document.InsertParagraph("Line 1\nLine 2\nLine 3");
// Indent only the first line of the Paragraph
p.IndentationFirstLine = 1.0f;
// Save all changes made to this document.
document.Save();
Console.WriteLine("\tCreated: docs\\Indentation.docx\n");
}
}

边距设置

        private static void DocumentMargins()
{
Console.WriteLine("\tDocumentMargins()"); // Create a document.
using (DocX document = DocX.Create(@"docs\DocumentMargins.docx"))
{ // Create a float var that contains doc Margins properties.
float leftMargin = document.MarginLeft;
float rightMargin = document.MarginRight;
float topMargin = document.MarginTop;
float bottomMargin = document.MarginBottom;
// Modify using your own vars.
leftMargin = 95F;
rightMargin = 45F;
topMargin = 50F;
bottomMargin = 180F; // Or simply work the margins by setting the property directly.
document.MarginLeft = leftMargin;
document.MarginRight = rightMargin;
document.MarginTop = topMargin;
document.MarginBottom = bottomMargin; // created bulleted lists var bulletedList = document.AddList("First Bulleted Item.", , ListItemType.Bulleted);
document.AddListItem(bulletedList, "Second bullet item");
document.AddListItem(bulletedList, "Sub bullet item", );
document.AddListItem(bulletedList, "Second sub bullet item", );
document.AddListItem(bulletedList, "Third bullet item"); document.InsertList(bulletedList); // Save this document.
document.Save(); Console.WriteLine("\tCreated: docs\\DocumentMargins.docx\n");
}
}

创建模板并设置自定义属性

      private static void CreateInvoice()
{
Console.WriteLine("\tCreateInvoice()");
DocX g_document; try
{
// Store a global reference to the loaded document.
g_document = DocX.Load(@"docs\InvoiceTemplate.docx"); /*
* The template 'InvoiceTemplate.docx' does exist,
* so lets use it to create an invoice for a factitious company
* called "The Happy Builder" and store a global reference it.
*/
g_document = CreateInvoiceFromTemplate(DocX.Load(@"docs\InvoiceTemplate.docx")); // Save all changes made to this template as Invoice_The_Happy_Builder.docx (We don't want to replace InvoiceTemplate.docx).
g_document.SaveAs(@"docs\Invoice_The_Happy_Builder.docx");
Console.WriteLine("\tCreated: docs\\Invoice_The_Happy_Builder.docx\n");
} // The template 'InvoiceTemplate.docx' does not exist, so create it.
catch (FileNotFoundException)
{
// Create and store a global reference to the template 'InvoiceTemplate.docx'.
g_document = CreateInvoiceTemplate(); // Save the template 'InvoiceTemplate.docx'.
g_document.Save();
Console.WriteLine("\tCreated: docs\\InvoiceTemplate.docx"); // The template exists now so re-call CreateInvoice().
CreateInvoice();
}
}
// Create an invoice for a factitious company called "The Happy Builder".
private static DocX CreateInvoiceFromTemplate(DocX template)
{
#region Logo
// A quick glance at the template shows us that the logo Paragraph is in row zero cell 1.
Paragraph logo_paragraph = template.Tables[].Rows[].Cells[].Paragraphs[];
// Remove the template Picture that is in this Paragraph.
logo_paragraph.Pictures[].Remove(); // Add the Happy Builders logo to this document.
RelativeDirectory rd = new RelativeDirectory(); // prepares the files for testing
rd.Up();
Image logo = template.AddImage(rd.Path + @"\images\logo_the_happy_builder.png"); // Insert the Happy Builders logo into this Paragraph.
logo_paragraph.InsertPicture(logo.CreatePicture());
#endregion #region Set CustomProperty values
// Set the value of the custom property 'company_name'.
template.AddCustomProperty(new CustomProperty("company_name", "The Happy Builder")); // Set the value of the custom property 'company_slogan'.
template.AddCustomProperty(new CustomProperty("company_slogan", "No job too small")); // Set the value of the custom properties 'hired_company_address_line_one', 'hired_company_address_line_two' and 'hired_company_address_line_three'.
template.AddCustomProperty(new CustomProperty("hired_company_address_line_one", "The Crooked House,"));
template.AddCustomProperty(new CustomProperty("hired_company_address_line_two", "Dublin,"));
template.AddCustomProperty(new CustomProperty("hired_company_address_line_three", "")); // Set the value of the custom property 'invoice_date'.
template.AddCustomProperty(new CustomProperty("invoice_date", DateTime.Today.Date.ToString("d"))); // Set the value of the custom property 'invoice_number'.
template.AddCustomProperty(new CustomProperty("invoice_number", )); // Set the value of the custom property 'hired_company_details_line_one' and 'hired_company_details_line_two'.
template.AddCustomProperty(new CustomProperty("hired_company_details_line_one", "Business Street, Dublin, 12345"));
template.AddCustomProperty(new CustomProperty("hired_company_details_line_two", "Phone: 012-345-6789, Fax: 012-345-6789, e-mail: support@thehappybuilder.com"));
#endregion /*
* InvoiceTemplate.docx contains a blank Table,
* we want to replace this with a new Table that
* contains all of our invoice data.
*/
Table t = template.Tables[];
Table invoice_table = CreateAndInsertInvoiceTableAfter(t, ref template);
t.Remove(); // Return the template now that it has been modified to hold all of our custom data.
return template;
} // Create an invoice template.
private static DocX CreateInvoiceTemplate()
{
// Create a new document.
DocX document = DocX.Create(@"docs\InvoiceTemplate.docx"); // Create a table for layout purposes (This table will be invisible).
Table layout_table = document.InsertTable(, );
layout_table.Design = TableDesign.TableNormal;
layout_table.AutoFit = AutoFit.Window; // Dark formatting
Formatting dark_formatting = new Formatting();
dark_formatting.Bold = true;
dark_formatting.Size = ;
dark_formatting.FontColor = WindowsColor.FromArgb(, , ); // Light formatting
Formatting light_formatting = new Formatting();
light_formatting.Italic = true;
light_formatting.Size = ;
light_formatting.FontColor = WindowsColor.FromArgb(, , ); #region Company Name
// Get the upper left Paragraph in the layout_table.
Paragraph upper_left_paragraph = layout_table.Rows[].Cells[].Paragraphs[]; // Create a custom property called company_name
CustomProperty company_name = new CustomProperty("company_name", "Company Name"); // Insert a field of type doc property (This will display the custom property 'company_name')
layout_table.Rows[].Cells[].Paragraphs[].InsertDocProperty(company_name, f: dark_formatting); // Force the next text insert to be on a new line.
upper_left_paragraph.InsertText("\n", false);
#endregion #region Company Slogan
// Create a custom property called company_slogan
CustomProperty company_slogan = new CustomProperty("company_slogan", "Company slogan goes here."); // Insert a field of type doc property (This will display the custom property 'company_slogan')
upper_left_paragraph.InsertDocProperty(company_slogan, f: light_formatting);
#endregion #region Company Logo
// Get the upper right Paragraph in the layout_table.
Paragraph upper_right_paragraph = layout_table.Rows[].Cells[].Paragraphs[]; // Add a template logo image to this document.
RelativeDirectory rd = new RelativeDirectory(); // prepares the files for testing
rd.Up();
Image logo = document.AddImage(rd.Path + @"\images\logo_template.png"); // Insert this template logo into the upper right Paragraph.
upper_right_paragraph.InsertPicture(logo.CreatePicture()); upper_right_paragraph.Alignment = Alignment.right;
#endregion // Custom properties cannot contain newlines, so the company address must be split into 3 custom properties.
#region Hired Company Address
// Create a custom property called company_address_line_one
CustomProperty hired_company_address_line_one = new CustomProperty("hired_company_address_line_one", "Street Address,"); // Get the lower left Paragraph in the layout_table.
Paragraph lower_left_paragraph = layout_table.Rows[].Cells[].Paragraphs[];
lower_left_paragraph.InsertText("TO:\n", false, dark_formatting); // Insert a field of type doc property (This will display the custom property 'hired_company_address_line_one')
lower_left_paragraph.InsertDocProperty(hired_company_address_line_one, f: light_formatting); // Force the next text insert to be on a new line.
lower_left_paragraph.InsertText("\n", false); // Create a custom property called company_address_line_two
CustomProperty hired_company_address_line_two = new CustomProperty("hired_company_address_line_two", "City,"); // Insert a field of type doc property (This will display the custom property 'hired_company_address_line_two')
lower_left_paragraph.InsertDocProperty(hired_company_address_line_two, f: light_formatting); // Force the next text insert to be on a new line.
lower_left_paragraph.InsertText("\n", false); // Create a custom property called company_address_line_two
CustomProperty hired_company_address_line_three = new CustomProperty("hired_company_address_line_three", "Zip Code"); // Insert a field of type doc property (This will display the custom property 'hired_company_address_line_three')
lower_left_paragraph.InsertDocProperty(hired_company_address_line_three, f: light_formatting);
#endregion #region Date & Invoice number
// Get the lower right Paragraph from the layout table.
Paragraph lower_right_paragraph = layout_table.Rows[].Cells[].Paragraphs[]; CustomProperty invoice_date = new CustomProperty("invoice_date", DateTime.Today.Date.ToString("d"));
lower_right_paragraph.InsertText("Date: ", false, dark_formatting);
lower_right_paragraph.InsertDocProperty(invoice_date, f: light_formatting); CustomProperty invoice_number = new CustomProperty("invoice_number", );
lower_right_paragraph.InsertText("\nInvoice: ", false, dark_formatting);
lower_right_paragraph.InsertText("#", false, light_formatting);
lower_right_paragraph.InsertDocProperty(invoice_number, f: light_formatting); lower_right_paragraph.Alignment = Alignment.right;
#endregion // Insert an empty Paragraph between two Tables, so that they do not touch.
document.InsertParagraph(string.Empty, false); // This table will hold all of the invoice data.
Table invoice_table = document.InsertTable(, );
invoice_table.Design = TableDesign.LightShadingAccent1;
invoice_table.Alignment = Alignment.center; // A nice thank you Paragraph.
Paragraph thankyou = document.InsertParagraph("\nThank you for your business, we hope to work with you again soon.", false, dark_formatting);
thankyou.Alignment = Alignment.center; #region Hired company details
CustomProperty hired_company_details_line_one = new CustomProperty("hired_company_details_line_one", "Street Address, City, ZIP Code");
CustomProperty hired_company_details_line_two = new CustomProperty("hired_company_details_line_two", "Phone: 000-000-0000, Fax: 000-000-0000, e-mail: support@companyname.com"); Paragraph companyDetails = document.InsertParagraph(string.Empty, false);
companyDetails.InsertDocProperty(hired_company_details_line_one, f: light_formatting);
companyDetails.InsertText("\n", false);
companyDetails.InsertDocProperty(hired_company_details_line_two, f: light_formatting);
companyDetails.Alignment = Alignment.center;
#endregion // Return the document now that it has been created.
return document;
}

DocX开源WORD操作组件的学习系列四的更多相关文章

  1. DocX开源WORD操作组件的学习系列三

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  2. DocX开源WORD操作组件的学习系列二

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  3. DocX开源WORD操作组件的学习系列一

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  4. 开源word操作组件DocX的记录

    开源word操作组件DocX的记录 使用开源word操作组件DocX的记录 1.DocX简介 1.1 简介 DocX是一个在不需要安装word的情况下对word进行操作的开源轻量级.net组件,是由爱 ...

  5. 使用开源word操作组件DocX的记录

    1.DocX简介 1.1 简介 DocX是一个在不需要安装word的情况下对word进行操作的开源轻量级.net组件,是由爱尔兰的一个叫Cathal Coffey的博士生开发出来的.DocX使得操作w ...

  6. 开源Word读写组件DocX 的深入研究和问题总结

    一. 前言 前两天看到了asxinyu大神的[原创]开源Word读写组件DocX介绍与入门,正好我也有类似的自动生成word文档得需求,于是便仔细的研究了这个DocX. 我也把它融入到我的项目当中并进 ...

  7. [.NET] 开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc

    开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc [博主]反骨仔 [原文地址]http://www.cnblogs.com/li ...

  8. 开源RabbitMQ操作组件

    开源RabbitMQ操作组件 对于目前大多的.NET项目,其实使用的技术栈都是差不多,估计现在很少用控件开发项目的了,毕竟一大堆问题.对.NET的项目,目前比较适合的架构ASP.NET MVC,ASP ...

  9. scrapy爬虫学习系列四:portia的学习入门

    系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...

随机推荐

  1. 关于阿里ICON矢量图(SVG)上传问题.

    注意点: 1. 存储为svg格式(建议使用存储为svg,不要使用导出为svg)2. 图像位置:链接(注意哦,不要点嵌入和保留编辑功能)---确定3. AI里面选中图形,点对象-路径-轮廓化描边 软件编 ...

  2. python爬虫实践(一)

    最近在学习爬虫,学完后想实践一下,所以现在准备爬取校花网的一部分图片 第一步,导入需要的库 from urllib import request #用于处理request请求和获得响应 from ur ...

  3. Hive参数的临时设置和永久性设置

    Hive中有一些参数是系统给提供给用户的,我们可以通过这些参数的设置可以让Hive在不同的模式下工作,或者改变显示的效果. 1.通过set对参数值进行设定,这种设置只能是在本次会话有效,退出Hive就 ...

  4. Git 实用指南

    传送门: https://mp.weixin.qq.com/s?__biz=MzI3MzgxNDY2MQ==&mid=2247484159&idx=1&sn=2d28513ef ...

  5. 如何给网站添加IE浏览器升级提示

    1.在代码编辑器中(如Notepad++)打开网站头部模板 2.使用<!––[if IE]>语句添加升级提示,如: 判断是否IE(包含使用IE内核的浏览器) <!––[if IE]& ...

  6. MySQL 中 having 和 where 的区别

    区别一: where 是数据从磁盘读入内存时候一条一条判断的 having 是将所有数据读入内存,在分组统计前,根据having的条件再将不符合条件的数据删除 区别二: having 子句可以使用字段 ...

  7. K8S 安装 Wordpress

    基本概念 Helm 可以理解为 Kubernetes 的包管理工具,可以方便地发现.共享和使用为Kubernetes构建的应用,它包含几个基本概念 Helm是目前Kubernetes服务编排领域的唯一 ...

  8. s:if 判断 s:property

    判断<s:property value="XXX"/> 是否是空字符串 则:<s:if  test=" XXX == ''  ">< ...

  9. angular.js学习笔记(一)

    1.angular单项数据绑定 2.不要使用控制器的时候: 任何形式的DOM操作:控制器只应该包含业务逻辑.DOM操作则属于应用程序的表现层逻辑操作,向来以测试难度之高闻名于业界.把任何表现层的逻辑放 ...

  10. java中级或者高级面试题分享

    一. 基础知识: 1)集合类:List和Set比较,各自的子类比较(ArrayList,Vector,LinkedList:HashSet,TreeSet): 2)HashMap的底层实现,之后会问C ...