Java基础day17笔记:Collecitons-sort/max/binarySearch/替换反转/reverseOrder/SynList|Arrays|集合转成数组|增强for循环|可...

    10-集合(Collections-sort)

        集合框架我们基本都讲完了,就剩下了这一部分,工具类:

        首先说一下Collections,它的出现有什么特点呢?

        作为一个工具类,首先它里面的方法都是静态的。

        它没有对外提供构造函数,是不需要创建对象的,因为它的对象当中并未去封装特有数据,都是共享型的情况下,定义成静态最方便。

        它的里面有一堆方法,都有什么用呢?

        我现在有一堆元素,不需要保证唯一,用哪个集合?List。

        可是我又想对这里面的元素进行排序。但Tree是Set集合中的,List集合中没有直接排序的方式。

        那么集合框架也想到了,它为我们提供了这样一个工具来完成这个动作。

        Colletions这个工具类是专门用来对集合进行操作的。

        那么,它里面是由n多静态方法所组成的,其中有一个看上去就很爽:

        它可以对List集合进行排序。

        我们先分析一下红框这一部分:

        1.4版本的写法:

        1.5开始,就带泛型了:

        List集合中的元素想要排序是不是需要进行比较?

        所以这个T必须是Comparable的子类:

        Comparable这个接口也带泛型,所以写个T:

        但是为了扩展性更强一些,里面传T的父类也可以:

        OK,现在整体都理解了。

        接下来我们来用一下。

        代码:

        结果:

        List是数组结构,数组结构出现重复元素后依然可以排序,因为它有索引,例:

        接下来我们想改一下排序规则,想对集合中的字符串进行长度排序。

        我们发现还有一个带比较器的sort方法:

        代码实现: 

    11-集合(Collections-max)

        接下来我们看一下Collections中的max方法:        

        试一下:

        上面这个是按自然顺序排。

        下面这个是按照自定义的长度顺序排:

    12-集合(Collections-binarySearch)

        试一下:

        试着找一下集合中不存在的"aaaa":

        这个2是什么呢?

        我们点进binarySearch方法中看一下:

        所以这里返回的是-1-1=-2。

        下面写一下binarySearch的原理:

        验证一下,找一下"aaa":

        再试着找一下"aaaa":

        我们的返回值不够专业,修改一下,返回-(插入点)-1:

        OK啦:

        如果元素不具备比较性怎么办?

        那就用这个方法,具有比较器的:

        这个方法的原理,将上面写的那部分原理代码拿下来,做两处修改即可:

        做这两处修改是因为,原先是str.compare....,但是str有可能不具备比较性,或者它的比较方式不是我们所需要的,这个时候就指定了一个比较器cmp,cmp中有一个compare方法,用这个方法来对str和key做比较。

        而比较器的compare方法就是之前写的按长度来比的:

        现在试一下使用它:

    13-集合(Collections-替换反转)

        接下来演示一下fill方法:

        演示:

        这个方法将集合中的元素全部都替换成了指定的元素。

        接下来做一个小练习:fill方法可以将list集合中的所有元素替换成指定元素,我们现在来实现一下将list集合中的部分元素替换成指定元素。

        思路:

        接下来看一下replaceAll方法:

        演示: 

    14-集合(Collections-reverseOrder)

        用迭代器打印出TreeSet集合中的元素:

        现在我们想将它倒序打印出来,是不是不再用它默认的比较方式,而是传一个比较器。

        比较器:

        但是老需要这么写还是很麻烦,我们要想一想,集合框架中是否提供了这样的方法?没有的话我们才需要自己手动来写。

        在Collections中就有这样一个方法:

        所以我们直接把这个逆向比较器传入就可以了:

        实现了元素的逆序输出:

        我们之前写了一个按长度来排序的比较器,排序出来的结果是从短到长,我们现在想实现从长到短的排序,该怎么做呢?

        Collections中还有一个方法,可以将一个现有的比较器强行逆转,就是刚刚那个逆向比较器的重载方法,刚刚那个逆向比较器没有参数,而这个方法可以传一个比较器:

        这样即可:

        OK了:

    15-集合(Collections-SynList)

        集合中那么多的对象,它们都有一个共同的特点:线程不安全。万一真的被多线程操作了,就会出问题。

        那该怎么办呢?

        自己加锁?

        很麻烦的。

        添加有一个方法,删除有一个方法,我们需要将添加和删除封装到同一个锁里面去,也就是说,在某一时刻,只能有一个线程进行添加或者删除。

        怎么办呢?

        Collecitons就替我们想到了解决方法:

        我们只要将不安全的集合给它,它就会给我们安全的集合。

        这个不需要演示,我们更想知道它底层是怎么实现的。

        下面要介绍源码:

        这里有个SynchronizedList类,我们来看一下:

        我们找到它的添加和删除方法:

        这就是它的实现原理。添加和删除是两个动作,这两个动作要放在一个锁里面才行。

        顺便再说一下swap方法:

        reverse方法在反转的时候需要调换元素在集合中的位置,其实调换的时候就是调用的swap方法来完成。

        将它暴露出来,就可以直接置换List集合中两个元素的位置。

        演示一下:

        顺便再提一下shuffle这个方法:

        对列表中元素位置进行随机置换,听起来很厉害的样子,我们试一下:

        两次运行的结果是不同的,都是随机的。

        其实和洗牌、摇色子一样,以后写相关的代码可以用到。

    16-集合(Arrays)

        Arrays:用于操作数组的工具类。

        里面都是静态方法。

        接下来演示一些方法。

        将数组变成字符串:

        将数组变成List集合(传进来一个数组,返回的是List):

        演示:

        把数组变成List集合有什么好处?

        以前我们要判断一个元素在数组中是否存在,需要遍历这个数组,然后写判断方式,自己完成这个功能就比较麻烦:

        而把数组变成集合之后,我们就可以使用集合的思想和方法来操作数组中的元素:

        数组的方法比较少,集合的方法比较多。

        但是注意,我们执行这句代码:

        运行的时候会报错,不支持的操作异常:

        为什么会这样呢?

        注意:将数组变成集合之后,不可以使用集合的增删方法,因为数组的长度是固定的。如果使用了增删方法,就会发生UnsupportedOperationException。

        我们可以使用集合中诸如contains、get、indexOf()、subList()等方法。

        我们再试一下这个:

        我们发现打印出来的是一个数组的哈希值。

        为什么把字符串往里面一扔就变成集合了呢?

        如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转换成集合中的元素。

        如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。

        我们重新试一下:

        OK了:

    17-集合(集合转成数组)

        说完了数组变集合,接下来说集合变数组。

        该用什么方法呢?

        Collection接口中的toArray方法。

        这里有两个toArray方法:

        我们该用哪一个呢?

        第一个是返回Object类型的数组,第二是返回指定类型的数组,显然第二种更方便一些,就不用强转了。

        我们演示一下:

        为什么传0呢?我们传1试一试:

        运行结果没有什么区别:

        传5试试:

        有区别了:

        总结一下:

        1,指定类型的数组到底要定义多长呢?

        当指定类型的数组长度小于集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。

        当指定类型的数组长度大于集合的size,就不会新创建数组,而是使用传递进来的数组。

        所以创建一个刚刚好的数组最优。(创建短的也可以,但是内存中会多一个数组)

        2,为什么要将集合变数组?

        为了限定对元素的操作,不需要进行增删了。

    18-集合(增强for循环)

        Iterator方法虽然在以前的版本上已经做了改进和更新,方便了很多,可是这个单词也不好写,容易写错。

        接下来,Java在JDK1.5的时候,考虑到了我们的痛苦,帮我们解决了这个问题。

        1.5版本以后,Java给Collection找了个爹,它继承了Iterable接口:

        我们点进这个Iterable接口看看:

        它是1.5开始的。

        这个接口的出现,就是将迭代方法抽取出来了。

        这个接口的出现有什么好处呢?

        它不光是把这个迭代方法抽取出来提高了集合框架的扩展性(以后我们再出一个Collection2接口,只要继承这个Iterable方法,也可以具有迭代方法),另外它还给这个集合框架提供了一个新功能,就是高级for循环:

        这个foreach循环是什么东东呢?

        我们来讲一下高级for循环。

        格式:

        for(数据类型 变量名:被遍历的集合(Collection)或者数组)

        示例: 

        编译运行,也出来了:

        这个写法要比迭代器的写法简单太多。

        但是它底层的原理其实还是迭代器,只是将复杂代码编程简单代码了,这个升级是简化书写。

        s先指向“abc1”,再指向“abc2”,......,它指向的对象一直在变化。

        我们加一个小动作,看看会怎么样:

        打印结果还是原先的样子:

        所以这个循环具有局限性,它只能对集合中的元素进行取出,而不能进行修改。

        迭代器不会这样,迭代器至少还有一个remove删除,如果用列表迭代器(ListIterator),增删改查都行,所以是有区别的。

        所以简化书写虽然提供了很大方便,但是也有局限的地方。

        那么这个for循环和我们传统的for循环有区别吗?

        有的。

        传统for循环和高级for循环的区别:

        高级for有一个局限性,必须有被遍历的目标。

        举个例子,我们想将"hello world"打印100次,传统的for循环方法完全OK,但是高级for循环就无法简单粗暴的完成这个任务。

        所以,建议在遍历数组的时候,还是希望用传统for,因为传统for可以定义角标。

        新的例子:

        将HashMap中的键和值拿了出来:

        接下来我们用entrySet和高级for循环来完成:

        OK:

        另外要注意,ArrayList后面写了泛型,底下才能明确写String,如果没有写泛型,底下只能写Object。高级for循环是1.5版本出现的,泛型也是1.5版本出现的,所以上面带着泛型,下面就可以用泛型的类型。

    19-集合(可变参数)

        接下来讲另外一个JDK1.5版本出现的新特性。

        用例子来说: 

        虽然写好show方法调用它已经方便很多了,但是我们还能更方便。我们写了一个show方法,每次打印数组的时候直接调用这个方法就OK,但是,每次打印不同的数组,我们都得定义一个新的数组出来,作为实际参数,就有点麻烦了。

        1.5版本后,出现了一个新特性:

这是一个数组

         我们还可以打印数组的长度:

        介绍一下这个特性:可变参数

        其实就是上一种数组参数的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可,隐式将这些参数封装成了数组。

        写成了...,数组不用定义了,爱传几个传几个,不传都可以: 

        这个更新简化了开发代码,提高了开发速度。

        注意:方法的可变参数在使用时,可变参数一定要定义在参数列表最后面。

        例,这里String定义在前面,“haha”匹配给了它,其他的int型数据封装给了可变参数:

        这样运行是OK的。

        而String定义在后面,int...定义在前面,会默认将所有参数都封装到可变参数中,这样就会出问题了:

    20-集合(静态导入)

        接下来讲最后一个1.5版本的新特性:静态导入。

        这里面有一个小插曲,我们先演示一下:

        接下来我们用二分法查找一下1并打印:

        我们发现,每次使用工具类的时候,都要工具类名.。。。,稍微有点麻烦。

        再回想起之前,我们不导入工具类的包,就要这样写:

        而我们导入工具类包之后,这个包名前缀就可以省略了。

        而像Arrays和Collections等等这样的类中都是静态方法,我们把这些类导入的话,方法前面的工具类名是不是也可以省略了呢?

        我们试着这样做:

        编译运行都是OK的。(图略)

        但是忘记省略Arrays.toString(arr)了呀。

        我们也将它省略掉:

        但是编译运行就报错了:

        因为StaticImport类是继承了Object类的:

        Object类中也有一个toString方法,但是这个toString方法不可以传参数,于是就报错了。

        两个包中有同样的方法,一定要加包名来指定命名空间。

        当类名重名时,需要指定具体的包名。                                                                                          当方法重名时,需要指定所属的对象或者类。

        再举个更简单的例子来说明这个问题,packa包和packb包中都有Demo类,那么将它们都导入后,new一个Demo,到底new的是哪一个包中的Demo呢:

        这个时候必须要用指定的所属包名来区分:

        而我们现在导入的包里面有多个同名方法,而且是属于不同的类,Object中有toString,Arrays中也有toString,所以这个时候一定要标明到底是谁的toString。这样就没毛病啦:

        跟你讲喔,还有更爽的呢。

        天天自己写输出语句很麻烦,在java.lang包中有一个System类,这个类中有一个out属性:

        这个属性是静态的。

        System中全都是静态方法。

        我们也将System类中所有静态成员都导入:

        (最后两句前面的System都可以删掉了)

        总结一下,导入的时候,如果import后面没有跟静态static,导入的都是类:

        导入的时候,如果import后面跟了静态static,导入的都是类中的静态成员:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容