(java technic)collection部分笔记整理及作业(being revised)

2、remove


Iterator接口中的remove方法会删除上次next时返回的元素
例(delete <String> 中的first element)

Iterator<String>it=c.iterator();
it.next();//skip over the first elements
it.remove();//now remove it

more,对next 和 remove 的调用具有互相依赖性,如果remove之前没有调用next则是illegal的。如果这样,将会IllegalStateException
如果像删除两个相邻的element,不能直接这样调用

//wrong!
it.remove();
it.remove();//Error!
in fact:
we need next over the"deleted"element
//right
it.remove();
it.next();
it.remve();

3、泛型实用方法


 collection与iterator都是泛型接口,可以编写操作任何集合类型的实用方法
 例(check任意集合是否包含指定元素的泛型方法)

 public static<E>boolean contains(collection<E>c,Object obj)
 {
     for(E element:c)
         if(element.equals(obj))
             return true;
         return false;
    }

contains就是一个实用方法

具体集合
1、链表(linked list)
Preface:
数组及动态的ArrayList都存在一个重大缺陷,即从数组的中间位置删除一个元素要付出很大代价
解决:链表
链表将每个对象存放在独立的节点中,每个节点还存放着序列中下一个节点的引用。在Java中所有链表实际上都是doubly linked(双向链接)——即每个结点还存放着只想前驱结点的引用
那么从链表中删除一个元素,只需要对被删除元素附近的结点更新一下
例:(add 3 elements,then remove 2nd element)

List<String>staff=new LinkedList<>();//LinkedList implements List
staff.add("Amy");
staff.add("Bob");
staff.add("Carl");
Iterator iter=staff.iterator();
String first=iter.next();//visit first element
String second=iter.next();//visit second element
iter.remove();//remove last visited element

链表与泛型集合的一个区别:
链表是ordered collection,每个对象的位置都是important的
LinkedList.add方法将对象添加到链表的尾部
若添加到中间,由于迭代器是描述集合中位置的,so这组依赖于位置的add方法有迭代器负责,
只有对自然有序的collection使用迭代器添加元素才有实际意义。如集(set)类型,其中的element完全无序。
因此在iterator接口中就没有add方法。集合类库提供了子接口ListIterator,其中包含add方法:

interface ListIterator<E> extends Iterator<E>
{
    void add(E element);
    ...
    }

    与Collection.add不同在于,该方法不返回boolean类型的值,它假定add操作总会改变链表
    另外,ListIterator接口有两个方法,用来反向遍历链表
    E previous()
    boolean hasPrevious()
    与next一样,previous返回越过的对象
    add方法只依赖于迭代器位置,而remove方法依赖于迭代器state
ConcurrentModification   并发修改
列表迭代器接口还有一个方法,可以告知当前位置的索引。
同时产生两个索引:
nextIndex方法返回下一个调用next方法时返回元素的整数索引
previousIndex方法返回下一次调用previous方法时返回元素的整数索引
这个索引只比nextIndex返回的索引值小1
如果列表只有少数几个元素,完全可以使用ArrayList,
如果需要对集合进行随机访问,就使用数组或ArrayList
例:(创建两个链表,合并,从第二个链表中每隔一个元素删除一个元素,最后测试removeAll方法)
迭代器位置示意图(例)
    |ACE    |BDFG
    A|CE    |BDFG
    AB|CE    B|DFG
    . . .
    注意调用
    System.out.println(a);
    通过调用AbstractCollection类中的toString方法打印LinkedList a 中的所有元素

package linkedList;
import java.util.*;
//This program demonstrates operations on linked lists.

public class LinkedListTest
{
    public static void main(String[] args){
    List<String> a=new LinkedList<>();
    a.add("Amy");
    a.add("Carl");
    a.add("Eric");
    
    List<String> b=new LinkedList<>();
    b.add("Bob");
    b.add("Doug");
    b.add("Frank");
    b.add("Gloria");
    //merge the words from b into a
    ListIterator<String> aIte=a.ListIterator();
    Iterator<String> bIte=b.iterator();
    while(bIte.hasNext()){
    if(aIte.hasNext()) aIte.next();
    aIte.add(bIte.Next());
    }
    System.out.println(a);
    
    //remove every second word from b
    bIter=b.iterator();
    while(bIte.hasNext()){
    bIter.next();    //skip one element
    if(bIte.hasNext()){
    bIte.next();//skip next element
    bIte.remove();//remove that element
    }
    }
    System.out.println(b);
    //bulk operation:remove all words in b from a
    a.removeAll(b);
    System.out.println(a);
    }
    }

2?、散列集


need:快速查找所需要的对象---->散列表(hash table)
为每个对象计算一个hash code,是由对象的实例域产生的一个整数,具有不同数据域的对象将产生不同的hash code
    散列表可以用于实现几个重要的数据结构。最简单的是set类型。set是没有重复元素的元素集合。set的add方法首先在集中查找要添加的对象,如果不存在,就将这个对象加进去
    提供一个HashSet类,实现了基于hash table的集。contains方法已经被重新定义,用来快速查看是否某元素已经出现在集中。不关心集合中元素order时才用HashSet
4、树集


TreeSet类与散列集有类似,但有所改进。树集是一个sorted collection。可以以任意顺序将元素插入到集合中。在对集合进行遍历时,每个值将自动地按照排序后的顺序呈现
例:(假设插入3个字符串,然后访问添加的所有元素)

SortedSet<String> sorter=new TreeSet<>();//TreeSet implements SortedSet
sorted.add("Bob");
sorted.add("Amy");
sorted.add("Carl");
for(String s:sorter) System.println(s);

此时,每个值将按顺序打印出来
正如TreeSet类名,排序是用树结构完成的(now is red-black tree),每次将一个元素add进tree中,都被防止在正确的sorted position上,因此,迭代器总是以排好序的顺序访问每个元素
如果树中包含n个元素,查找new元素的正确位置平均需要log2n次比较。比如,包含1000个元素,add一个new element大约需要比较10次


5、对象的比较


treeSet如何知道希望元素怎样排列?默认情况下,TreeSet假定插入的元素实现了Comparable接口,该接口定义了一个方法:

public interface Comparable<T>{
int comparableTo(T other);
}

如果a与b相等,调用a.comparableTo(b)一定返回0;如果排序后a在b前,则返回负值,a在b后,正值,关键是符号(>0、<0或0)
如果插入自定义的对象,必须通过实现Comparable接口自定义排序顺序
在Object类中,没有提供任何compareTo接口的默认实现
例:(用部件编号对Item对象进行排序)

class Item implements Comparable<Item>{
    public int compareTo(Item other){
    return partNumber-other.partNumber;
    }
    . . .
}

如果对两个正整数进行比较,直接返回它们的差
warning:
只有整数在一个足够小的范围内,才可以使用这个技巧。如果x是一个较大的整整胡,y是一个较大的负整数,x-y可能溢出
while,使用Comparable接口定义排列排序具有明显的局限性。对于一个给定的类,只能实现一次这个接口。如果在一个集合中要按照部件编号排序,而另一个集合需要按照描述信息排序,如何解决?
此时,可以通过将Comparable对象传递给TreeSet构造器来告知TreeSet使用不同的compare方法。Comparator接口声明了一个带有两个显式参数的compare方法:

public interface Comparable<T>{
int compare(T a,T b);
}

与compareTo方法一样,a before b,negative;a equal b,zero;
如果按照描述信息进行排序,就直接定义一个实现Comparator接口的类
映射表(map)
提供了两个通用实现:HashMap和TreeMap
hash或比较函数只能作用于键
map接口常用方法
Object put(Object key,Object value)        
Object get(Object key)
Object remove(Object key)
int size()  return size number
Set keySet()        return key's collection

for() through arrays or Iterator 

算法:shuffle:
...

import java.util.*;

/**this program demonstrates the random shuffle and sort algorithms
*
*/

public class ShuffleTest{
    public static void main(String[] args){
    List<Integer>numbers=new ArrayList<>();
    for(int i=1;i<=49;i++)    number.add(i);
    Collections.shuffle(numbers);
    List<Integer>winningCombination=numbers.subList(0,6);
    Collections.sort(winningCombination);
    }
}

static<T extends Comparable<? super T>> void sort(List <T>) elements)
static <T> void sort(List<T> elements,Comparator<? super T> c)
使用稳定的排序算法,对列表中的元素进行排序。时间复杂度是O(n log n),
其中n为列表的长度
static void shuffle(List<?> elements)
static void shuffle(List<?> elements,Random r)
随机打乱列表中的元素。时间复杂度是O(n a(n)),n是列表长度,a(n)是随机访问元素的平均时间
static <T> Comparator<T> reverseOrder()
返回一个比较器,用Comparable接口的compareTo方法规定的顺序的逆序对元素进行排序
static<T> Comparator<T> reverseOrder(Comparator<T> comp)
返回一个比较器,用comp给定的顺序的逆序对元素进行排序

二分查找:


如果数组是有序的,就可以直接查看位于数组中间的元素,对比是否大于要查找的元素,如果是,则以相同方法在前半部分查找;否则,后半部分,缩减查找范围
Collection类的binarySearch方法实现了这个算法。attention:集合必须是排好序的,否则将返回错误的答案
像查找某个元素,必须提供集合(该集合要实现List接口)以继要查找的元素。如果集合没有采用Comparable接口的compareTo方法进行排序,就还要提供一个比较器对象
i= Collections.binarySearch(c,element);
i= Collections.binarySearch(c,element,comparator);
如果binarySearch方法返回数值>0,则表示匹配对象的index。即c.get(i)等于这个比较顺序下的element。如果<0,则没有匹配。可以利用返回值计算应该将element插入到集合的应在位置,保持集合有序性。
插入的位置是:
insertionPonit=-i-1;    (需要插入元素意味着i必然不是正数,即匹配不到这个元素)
attention:-i,因为0值是不确定的
if(i<0)        c.add(-i-1,element);
上述操作将把元素插入到正确的位置上
只有采用随机访问,二分查找才有意义。如果必须利用迭代方式一次次遍历链表的一般元素来查找中间位置的元素,二分查找就失去了优势。因此,如果为binarySearch算法提供一个链表,它将自动变为线性查找
static <T extends Comparable<? super T>> int binarySearch(List<T> elements,T key)
static <T> int binarySearch(List<T> elements,T key,Comparator<? super T> c)
从有序列表中搜索一个键,如果元素扩展了AbstractSequentialList类,则采用线性查找,否则二分查找。时间复杂度O(a(n) log n),n是列表长度,a(n)是访问一个元素的平均时间。该方法返回这个键在列表中的索引,如果在列表中不存在这个键将返回负值i,
此时,应该将这个键插入到列表索引 -i-1 的位置上,以保持列表的有序性
简单算法:    API注释描述Collections类的一些简单算法

编写自己的算法
如果编写自己的算法(是以集合为参数的任何方法),应尽可能使用接口,而不要使用具体的实现
如,假设想用一组菜单单项填充JMenu,这种方法可能会按照以下方法实现

void fillMenu(JMenu menu,ArrayList<JMenuItem> items){
    for(JMenuItem item:items)
    menu.add(item);
}

但是这样会限制方法的调用程序,即调用程序必须在ArrayList中提供选项。如果这些选项需要放在另一个容器中,
首先必须对它们重新包装。因此最好接受一个更通用的集合
找到完成这项工作最通用的集合接口?这里只需要访问所有的元素,这是Collection接口的基本功能。
以下说明了重新编写fillMenu方法使之接收任意type collections

void fillMenu(JMenu,Collection<JMenuItem>items){
    for(JMenuItem item:items)
        menu.add(item);
    }

now,anyone can use ArrayList or LinkedList,even use arrays packed by Arrays.asList wrapper 

如果编写了一个返回集合的方法,可能还想要一个返回接口,而不是返回类的方法,因此这样可以在日后change idea,并用另一个集合重新实现这个方法
例:(编写一个返回所有菜单的方法getAllItems)

List<JMenuItem> getAllItems(JMenu menu){
    List<JMenuItems> items=new ArrayList<>()
    for(int i=0;i<menu.getItemCount();i++)
        items.add(menu.getItem(i));
    return items;
}

日后可以这样编写:不复制所有的菜单项,而仅仅提供这些菜单项的视图,
要得到这个效果,只需要返回AbstractList的匿名子类

List<JMenuItem> getAllItems(final JMenu menu){
    return new AbstractList<>(){
        public JMenuItem get(int i){
            return menu.getItem(i);
            }
            public int size(){
                return menu.getItemCount();
            }
        };
    }

如果使用它,就应该将它支持的那些可选操作准确记录在文档中。此时,必须提醒调用者返回的对象是一个不可修改的列表

枚举:


Enumeration接口对元素序列进行遍历,Enumeration接口有两个方法,即
hasmoreElements和nextElements。这两个方法与Iterator接口的hasNext方法和next方法类似
例:(Hashtable类的elements方法将产生一个用于描述表中各个枚举值的对象:)

Enumeration<Employee>e =staff.elements();
while(e.hasMoreElements()){
    Employee e=e.nextElements();
    ...
}

静态方法Collections.enumeration将产生一个枚举对象,枚举集合中的元素
属性映射表(property map)
是一个type比较special的map结构。它有下面3个特性:
*键与值都是字符串
*表可以保存到一个文件中,也可以从文件中加载
*使用一个默认的辅助表
    实现property map的Java平台类称为Properties
    property map通常用于程序的特殊配置选项(chapter10)
    java util.Properties 1.0

栈:


从1.0开始,标准类库中就包含了Stack类,Stack类扩展为Vector类。可以让栈使用不属于栈操作的insert和remove方法,
即可以在任何地方进行插入或删除操作,而不仅仅是在栈顶
java.util.Stack<E> 1.0
E push(E item)    将item压入栈并返回item
E pop()            弹出并返回栈顶的item。如果栈为空,则不要调用该方法
E peek()        返回栈顶元素,但不弹出。如果栈为空,不要调用这个方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值