
众所周知,mybatis的传入参数可以是各种Java的基本数据类型:包含int,String,Date等。基本数据类型作为传参,只能传入一个。通过#{参数名} 即可获取传入的值 ,复杂数据类型:包含JAVA实体类、Map。通过#{属性名}或#{map的KeyName}即可获取传入的值,但是如果想传入一个collection怎么办呢?
经查找后发现可以使用mapper配置文件中的foreach语句,借用别人写的文章:
37 foreach
对于动态SQL 非常必须的,主是要迭代一个集合,通常是用于IN 条件。List 实例将使用“list”做为键,数组实例以“array” 做为键。
foreach元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。
注意:你可以传递一个List实例或者数组作为参数对象传给MyBatis。当你这么做的时候,MyBatis会自动将它包装在一个Map中,用名称在作为键。List实例将会以“list”作为键,而数组实例将会以“array”作为键。
这个部分是对关于XML配置文件和XML映射文件的而讨论的。下一部分将详细讨论Java API,所以你可以得到你已经创建的最有效的映射。
371参数为array示例的写法略372参数为list示例的写法
接口的方法声明:
Java代码
public List getStudentListByClassIds_foreach_list(List classIdList);
动态SQL语句:
Xml代码
<!-- 72 foreach(循环List参数) - 作为where中in的条件 -->
SELECT STSTUDENT_ID,
STSTUDENT_NAME,
STSTUDENT_SEX,
STSTUDENT_BIRTHDAY,
STSTUDENT_PHOTO,
STCLASS_ID,
STPLACE_ID
FROM STUDENT_TBL ST
WHERE STCLASS_ID IN
#{classIdList}
测试代码,查询学生中,在20000001、20000002这两个班级的学生:
Java代码
@Test
public void test7_2_foreach() {
ArrayList classIdList = new ArrayList();
classIdListadd("20000001");
classIdListadd("20000002");
List list = thisdynamicSqlMappergetStudentListByClassIds_foreach_list(classIdList);
for (StudentEntity e : list) {
Systemoutprintln(etoString());
}
}
这个是ItEye上的一篇文章,其中配置文件中的parameterType是可以不配置的,mybatis会自动传入的。当您想传入collection时,并不能直接传入collection对象,要将其先转换为list,然后才能传入。因为mybatis生成SQL语句遍历list时是需要用到get()方法的,而这个方法只在List中才有,Collection里是没有的。以上的配置在Mybitis官方文档中的“动态SQL”也可以找到。
参数示例:
根据班级ID查询教师列表
xml文件
[html] view plaincopy
select from Teacher where c_id=#{id}
java代码
[java] view plaincopy
List tList = teacherMapperselectTeacher(2);
for (Teacher entityTemp : tList) {
Systemoutprintln(entityTemptoString());
}
JAVA实体类型参数示例:
[html] view plaincopy
select from Teacher where c_id=#{id}
[java] view plaincopy
java代码
Teacher queryTeacher=new Teacher();
queryTeachersetId(2);
List tList = teacherMapperselectTeacher(queryTeacher);
for (Teacher entityTemp : tList) {
Systemoutprintln(entityTemptoString()); }
Map参数示例:
[html] view plaincopy
select from Teacher where c_id=#{id} and sex=#{sex}
[java] view plaincopy
java代码
Map map=new HasMap();
mapput("id","2");
mapput("sex","男");
List tList = teacherMapperselectTeacher(map);
for (Teacher entityTemp : tList) {
Systemoutprintln(entityTemptoString()); }
另外MyBatis还提供了一个使用注解来参入多个参数的方式。这种方式需要在接口的参数上添加@Param注解
示例:
接口方法
[java] view plaincopy
public List selectTeacher(@Param(value="id") String id,@Param(value="sex") String sex);
XML文件
[html] view plaincopy
select from Teacher where c_id=#{id} and sex=#{sex}
测试代码
[java] view plaincopy
List tList = teacherMapperselectTeacher("2","男");
for (Teacher entityTemp : tList) {
Systemoutprintln(entityTemptoString());
// 注意此处可以是任何集合类,不限于列表
Map 的特点是使用键值对的存储方式 使用存储时设置的键(key)读取
List 的特点是像数组一样的存储方式 使用下标读取
session 也是使用键值对的存储方式,但是他多数应用在网站作用域中。
主要区别在于根据编程中对数据的存储需求来应用。
个人认为应该在平常的项目设计过程中比较会有更贴切的理解。我是这么过来的。
我们知道 golang 中,slice, map, channel 是引用类型,函数之间传递都是以值拷贝的形式进行的,引用类型经过函数传递,依然是引用类型。
在上述例子中,我们从 map 中想拿出一个值,这个值是一个简单结构体,拿出这个值后,不确定这个值和 map 中的值是什么关系,如果不小心修改,是否会造成 map 值变更。
我们希望 golang 中更多的是值传递,这样能避免数据存储在堆上,造成 gc 负担。
可以看到,修改值后,map 中的值保持不变。说明 map 获取的值也是值传递出来的。
你写错了吧
vector 只支持一个数据类型的
就是遍历一次 2个循环
例子:
map<CString , vector<int>> map_value;for (map<CString , vector<int>>::iterator it1 = map_valuebegin(); it1 != map_valueend(); it1++)
{
// it1->first; it1->second;
for (vector<int>::iterator it2 = it1->secondbegin(); it2 != it1->secondend(); it2++)
{
// (it2) 就是vector里的int
}
}
Map存储key和对应的value。
1、Map()的特点:
(1) Map是一组键值对的形式 ,具有极快的查找速度;
(2)Map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。Set类似于数组,而Map就类似于键值对(Key, Value);
(3)Map是键值对的形式,通过键可以取到对应的值,键名不能重复;
(4)ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键;
(5)通过 展开运算符(…)可以把Map集合转换成包含多个数组的数组 。
背景,举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Array,给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,Array越长,耗时越长。
解决方法:使用Map 只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。
用JavaScript写一个Map如下:
2、Map用法实例:
3、Map的属性值说明:
var x=new Map();
(1) xset(‘a’,‘b’)添加键值
(2) xhas(‘a’)判断是否存在某个键值,返回true或false
(3) xdelete(‘a’)删除某个键
(4) xget(‘x’)获取键对应的值
(5) xsize获取有多少个元素
(6) xclear(),注“括号中没有参数”,清楚x对象中的所有元素。
(7) keys():返回键名的遍历器。
(8) values():返回键值的遍历器。
(9) entries():返回所有成员的遍历器。
(10) forEach():遍历 Map 的所有成员。
4、Map使用方法:
(1)初始化Map对象
(2)使用has判断某个键是否存在
(3)使用delete可以删除某个键
(4)使用get可以获取某个键的值
(5)清除所有的元素
注意:由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉。
实例:
上面代码在新建 Map 实例时,就指定了两个键name和title。
Map构造函数接受数组作为参数,实际上执行的是下面的算法。
下面的代码使用forEach实现:
用法看下面的实例:
Map 结构转为数组结构,比较快速的方法是使用扩展运算符(…)
1、特点:
(1)是一组key的集合,但不存储value;
(2)对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。Set中,key不能重复。如果出现重复的key,Set会自动过滤。Set没有索引,它的键和值是一个。
(3)Set()是一个类似数组解构,但它不是数组。它本身就是一个构造函数。
(4)它最主要的作用是去重。
(5)可以使用Arrayfrom()把它变成一个数组。
(6)通过展开运算符(…)可以把Set集合转换成一个数组。
2、用法
3、属性说明
var s=new Set();
(1) sadd(‘a’);添加一个元素
(2) sdelete(‘a’);删除一个元素
(3) ssize;获取元素的数量
(4) sclear()清除对象中的所有元素。
(5) shas(‘a’)判断s对象中是否有某个元素,返回true或false
4、可以使用多个add()连起来:
5、Set中的方法:
由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
6、使用forEach()
7、使用…扩展符可以把Set对象变成一个数组
8、也可以使用map和filter对Set对象进行处理
注:使用map和filter进行处理之前记得使用…把Set对象变成一个数组,再进行一系列 *** 作。
代码如下:
使用map:
使用map进行处理:
把数组变成Set类型:
使用filter:
使用 Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。
HashMap map = new HashMap<String,ArrayLisy<T>>();
T就是该链表的数据类型
增加一条记录
ArrayLisy<T> list = new ArrayLisy<T>();
mapput("item1",list);
基于hashing的原理,jdk8后采用数组+链表+红黑树的数据结构。我们通过put和get存储和获取对象。当我们给put()方法传递键和值时,先对键做一个hashCode()的计算来得到它在bucket数组中的位置来存储Entry对象。当获取对象时,通过get获取到bucket的位置,再通过键对象的equals()方法找到正确的键值对,然后在返回值对象。
当数组table的size达到阙值时即++size > load factor capacity 时,也是在putVal函数中。
扩容需要重新分配一个新数组,新数组是老数组的2倍长,然后遍历整个老结构,把所有的元素挨个重新hash分配到新结构中去。
对key的hashCode进行hashing,与运算计算下标获取bucket位置,如果在桶的首位上就可以找到就直接返回,否则在树中找或者链表中遍历找,如果有hash冲突,则利用equals方法去遍历链表查找节点。
对key的hashCode做hash *** 作,与高16位做异或运算。
还有平方取中法,除留余数法,伪随机数法。
因为数组位置的确定用的是与运算,仅仅最后四位有效,设计者将key的哈希值与高16为做异或运算使得在做&运算确定数组的插入位置时,此时的低位实际是高位与低位的结合,增加了随机性,减少了哈希碰撞的次数。
会产生哈希碰撞,若key值相同则替换旧值,不然链接到链表后面,链表长度超过阙值8就转为红黑树存储。
HashCode相同,通过equals比较内容获取值对象。
超过阙值会进行扩容 *** 作,概括的讲就是扩容后的数组大小是原数组的2倍,将原来的元素重新hashing放入到新的散列表中去。
相同点:都是存储key-value键值对的
不同点:
loadFactor表示HashMap的拥挤程度,影响hash *** 作到同一个数组位置的概率。默认loadFactor等于075,当HashMap里面容纳的元素已经达到HashMap数组长度的75%时,表示HashMap太挤了,需要扩容,在HashMap的构造器中可以定制loadFactor。
JDK 18 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。针对这种情况,JDK 18 中引入了 红黑树(查找时间复杂度为 O(logn))来优化这个问题。但是链表大于8的概率是非常非常低的。
选择Integer,String这种不可变的类型,像对String的一切 *** 作都是新建一个String对象,对新的对象进行拼接分割等,这些类已经很规范的覆写了hashCode()以及equals()方法。作为不可变类天生是线程安全的。如果要使用自定义类做为Key,就需要重写hashCode()以及equals()方法。红黑树在做比较的时候使用的是SystemidentityHashCode()方法,是不需要做特殊处理的。
更多内容戳这里(整理好的各种文集)
以上就是关于怎么获得Map<String,Date>中 String或Date类型全部的内容,包括:怎么获得Map<String,Date>中 String或Date类型、java中Map、list、session都可以用来存储值,那位高手有他们的详细功能介绍,以及他们之间的区别,做好有、golang 从 map 获取值时的值拷贝问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)