首页 文章 精选 留言 我的

精选列表

搜索[面试],共5094篇文章
优秀的个人博客,低调大师

【漫画】以后在有面试官问你AVL树,你就把这篇文章扔给他。

背景 西天取经的路上,一样上演着编程的乐趣..... 1、若它的左子树不为空,则左子树上所有的节点值都小于它的根节点值。 2、若它的右子树不为空,则右子树上所有的节点值均大于它的根节点值。 3、它的左右子树也分别可以充当为二叉查找树。 例如: 例如,我现在想要查找数值为14的节点。由于二叉查找树的特性,我们可以很快着找到它,其过程如下: 1、和根节点9比较 2、由于 14 > 9,所以14只可能存在于9的右子树中,因此查看右孩子13 3、由于 14 > 13,所以继续查看13的右孩子15 4、由于 14 < 15,所以14只可能存在于15的左孩子中,因此查找15的左孩子14 5、这时候发现14正是自己查找的值,于是查找结束。 这种查找二叉树的查找正是二分查找的思想,可以很快着找到目的节点,查找所需的最大次数等同于二叉查找树的高度。 在插入的时候也是一样,通过一层一层的比较,最后找到适合自己的位置。 初始的二叉查找树只有三个节点: 然后我们按照顺序陆续插入节点 4,3,2,1,0。插入之后的结构如下: 这是一种比查找二叉树还特别的树哦,这种树就可以帮助我们解决二叉查找树刚才的那种所有节点都倾向一边的缺点的。具有如下特性: 具有二叉查找树的全部特性。 每个节点的左子树和右子树的高度差至多等于1。 例如:图一就是一颗AVL树了,而图二则不是(节点右边标的是这个节点的高度)。 对于图二,因为节点9的左孩子高度为2,而右孩子高度为0。他们之间的差值超过1了。 这种树就可以保证不会出现大量节点偏向于一边的情况了。 听起来这种树还不错,可以对于图1,如果我们要插入一个节点3,按照查找二叉树的特性,我们只能把3作为节点4的左子树插进去,可是插进去之后,又会破坏了AVL树的特性,那我们那该怎么弄? 右旋 我们在进行节点插入的时候,可能会出现节点都倾向于左边的情况,例如: 我们把这种倾向于左边的情况称之为左-左型。这个时候,我们就可以对节点9进行右旋操作,使它恢复平衡。 即:顺时针旋转两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子 再举个例子: 节点4和9高度相差大于1。由于是左孩子的高度较高,此时是左-左型,进行右旋。 这里要注意,节点4的右孩子成为了节点6的左孩子了 我找了个动图,尽量这个动图和上面例子的节点不一样。 左旋 左旋和右旋一样,就是用来解决当大部分节点都偏向右边的时候,通过左旋来还原。例如: 我们把这种倾向于右边的情况称之为右-右型。 我也找了一张动图。 例子讲解 初始状态如下: 然后我们主键插入如下数值:1,4,5,6,7,10,9,8 插入 1 左-左型,需要右旋调整。 插入4 继续插入 5 右-右型,需要左旋转调整。 继续插入6 右-右型,需要进行左旋 继续插入7 右-右型,需要进行左旋 继续插入10 继续插入9 出现了这种情况怎么办呢?对于这种右-左型的情况,单单一次左旋或右旋是不行的,下面我们先说说如何处理这种情况。 这种我们就把它称之为右-左 型吧。处理的方法是先对节点10进行右旋把它变成右-右型。 然后在进行左旋。 所以对于这种右-左型的,我们需要进行一次右旋再左旋。 同理,也存在左-右型的,例如: 对于左-右型的情况和刚才的 右-左型相反,我们需要对它进行一次左旋,再右旋。 回到刚才那道题 对它进行右旋再左旋。 到此,我们的插入就结束了。 总结一下 在插入的过程中,会出现一下四种情况破坏AVL树的特性,我们可以采取如下相应的旋转。 1、左-左型:做右旋。 2、右-右型:做左旋转。 3、左-右型:先做左旋,后做右旋。 4、右-左型:先做右旋,再做左旋。 不知道大家发现规律没,这个规则还是挺好记。 代码实现 //定义节点class AvlNode {intdata; AvlNode lchild;//左孩子AvlNode rchild;//右孩子intheight;//记录节点的高度}//在这里定义各种操作publicclass AVLTree{//计算节点的高度staticintheight(AvlNode T) {if(T ==null) {return-1; }else{returnT.height; } }//左左型,右旋操作staticAvlNode R_Rotate(AvlNode K2) { AvlNode K1;//进行旋转K1 = K2.lchild; K2.lchild = K1.rchild; K1.rchild = K2;//重新计算节点的高度K2.height= Math.max(height(K2.lchild),height(K2.rchild)) +1; K1.height= Math.max(height(K1.lchild),height(K1.rchild)) +1;returnK1; }//进行左旋staticAvlNode L_Rotate(AvlNode K2) { AvlNode K1; K1 = K2.rchild; K2.rchild = K1.lchild; K1.lchild = K2;//重新计算高度K2.height= Math.max(height(K2.lchild),height(K2.rchild)) +1; K1.height= Math.max(height(K1.lchild),height(K1.rchild)) +1;returnK1; }//左-右型,进行右旋,再左旋staticAvlNode R_L_Rotate(AvlNode K3) {//先对其孩子进行左旋K3.lchild = R_Rotate(K3.lchild);//再进行右旋returnL_Rotate(K3); }//右-左型,先进行左旋,再右旋staticAvlNode L_R_Rotate(AvlNode K3) {//先对孩子进行左旋K3.rchild = L_Rotate(K3.rchild);//在右旋returnR_Rotate(K3); }//插入数值操作staticAvlNode insert(intdata, AvlNode T) {if(T ==null) { T =newAvlNode(); T.data = data; T.lchild = T.rchild =null; }elseif(data < T.data) {//向左孩子递归插入T.lchild = insert(data, T.lchild);//进行调整操作//如果左孩子的高度比右孩子大2if(height(T.lchild) -height(T.rchild) ==2) {//左-左型if(data < T.lchild.data) { T = R_Rotate(T); }else{//左-右型T = R_L_Rotate(T); } } }elseif(data > T.data) { T.rchild = insert(data, T.rchild);//进行调整//右孩子比左孩子高度大2if(height(T.rchild) -height(T.lchild) ==2)//右-右型if(data > T.rchild.data) { T = L_Rotate(T); }else{ T = L_R_Rotate(T); } }//否则,这个节点已经在书上存在了,我们什么也不做//重新计算T的高度T.height= Math.max(height(T.lchild),height(T.rchild)) +1;returnT; }} 提示:可以左右拉动 希望通过这种漫画的形式,能够让你们更加容易读懂一些算法或数据结构。 欢迎工作一到五年的Java工程师朋友们加入Java填坑之路:860113481 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

优秀的个人博客,低调大师

【面试必备】透过源码角度一步一步带你分析 ArrayList 扩容机制

该文已加入开源文档:JavaGuide(一份涵盖大部分Java程序员所需要掌握的核心知识)。地址:https://github.com/Snailclimb/JavaGuide. 一 先从 ArrayList 的构造函数说起 ArrayList有三种方式来初始化,构造方法源码如下: /** * 默认初始容量大小 */ private static final int DEFAULT_CAPACITY = 10; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** *默认构造函数,使用初始容量10构造一个空列表(无参数构造) */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** * 带初始容量参数的构造函数。(用户自己指定容量) */ public ArrayList(int initialCapacity) { if (initialCapacity > 0) {//初始容量大于0 //创建initialCapacity大小的数组 this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) {//初始容量等于0 //创建空数组 this.elementData = EMPTY_ELEMENTDATA; } else {//初始容量小于0,抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } /** *构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回 *如果指定的集合为null,throws NullPointerException。 */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[](see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } } 细心的同学一定会发现 :以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为10。 下面在我们分析 ArrayList 扩容时会降到这一点内容! 二 一步一步分析 ArrayList 扩容机制 这里以无参构造函数创建的 ArrayList 为例分析 1. 先来看 add 方法 /** * 将指定的元素追加到此列表的末尾。 */ public boolean add(E e) { //添加元素之前,先调用ensureCapacityInternal方法 ensureCapacityInternal(size + 1); // Increments modCount!! //这里看到ArrayList添加元素的实质就相当于为数组赋值 elementData[size++] = e; return true; } 2. 再来看看 ensureCapacityInternal() 方法 可以看到 add 方法 首先调用了ensureCapacityInternal(size + 1) //得到最小扩容量 private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 获取默认的容量和传入参数的较大值 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } 当 要 add 进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity 为10。 3. ensureExplicitCapacity() 方法 如果调用 ensureCapacityInternal() 方法就一定会进过(执行)这个方法,下面我们来研究一下这个方法的源码! //判断是否需要扩容 private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) //调用grow方法进行扩容,调用此方法代表已经开始扩容了 grow(minCapacity); } 我们来仔细分析一下: 当我们要 add 进第1个元素到 ArrayList 时,elementData.length 为0 (因为还是一个空的 list),因为执行了 ensureCapacityInternal() 方法 ,所以 minCapacity 此时为10。此时,minCapacity - elementData.length > 0 成立,所以会进入 grow(minCapacity) 方法。 当add第2个元素时,minCapacity 为2,此时e lementData.length(容量)在添加第一个元素后扩容成 10 了。此时,minCapacity - elementData.length > 0 不成立,所以不会进入 (执行)grow(minCapacity) 方法。 添加第3、4···到第10个元素时,依然不会执行grow方法,数组容量都为10。 直到添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。进入grow方法进行扩容。 4. grow() 方法 /** * 要分配的最大数组大小 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * ArrayList扩容的核心方法。 */ private void grow(int minCapacity) { // oldCapacity为旧容量,newCapacity为新容量 int oldCapacity = elementData.length; //将oldCapacity 右移一位,其效果相当于oldCapacity /2, //我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍, int newCapacity = oldCapacity + (oldCapacity >> 1); //然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量, if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE, //如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍! 记清楚了!不是网上很多人说的 1.5 倍+1! ">>"(移位运算符):>>1 右移一位相当于除2,右移n位相当于除以 2 的 n 次方。这里 oldCapacity 明显右移了1位所以相当于oldCapacity /2。对于大数据的2进制运算,位移运算符比那些普通运算符的运算要快很多,因为程序仅仅移动一下而已,不去计算,这样提高了效率,节省了资源 我们再来通过例子探究一下grow() 方法 : 当add第1个元素时,oldCapacity 为0,经比较后第一个if判断成立,newCapacity = minCapacity(为10)。但是第二个if判断不会成立,即newCapacity 不比 MAX_ARRAY_SIZE大,则不会进入 hugeCapacity 方法。数组容量为10,add方法中 return true,size增为1。 当add第11个元素进入grow方法时,newCapacity为15,比minCapacity(为11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中return true,size增为11。 以此类推······ 这里补充一点比较重要,但是容易被忽视掉的知识点: java 中的 length 属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了 length 这个属性. java 中的 length() 方法是针对字符串说的,如果想看这个字符串的长度则用到 length() 这个方法. java 中的 size() 方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看! 5. hugeCapacity() 方法。 从上面 grow() 方法源码我们知道: 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) hugeCapacity() 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,如果minCapacity大于最大容量,则新容量则为Integer.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 Integer.MAX_VALUE - 8。 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); //对minCapacity和MAX_ARRAY_SIZE进行比较 //若minCapacity大,将Integer.MAX_VALUE作为新数组的大小 //若MAX_ARRAY_SIZE大,将MAX_ARRAY_SIZE作为新数组的大小 //MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } 三 System.arraycopy() 和 Arrays.copyOf()方法 阅读源码的话,我们就会发现 ArrayList 中大量调用了这两个方法。比如:我们上面讲的扩容操作以及add(int index, E element)、toArray() 等方法中都用到了该方法! 3.1 System.arraycopy() 方法 /** * 在此列表中的指定位置插入指定的元素。 *先调用 rangeCheckForAdd 对index进行界限检查;然后调用 ensureCapacityInternal 方法保证capacity足够大; *再将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。 */ public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! //arraycopy()方法实现数组自己复制自己 //elementData:源数组;index:源数组中的起始位置;elementData:目标数组;index + 1:目标数组中的起始位置; size - index:要复制的数组元素的数量; System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } 我们写一个简单的方法测试以下: public class ArraycopyTest { public static void main(String[] args) { // TODO Auto-generated method stub int[] a = new int[10]; a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3; System.arraycopy(a, 2, a, 3, 3); a[2]=99; for (int i = 0; i < a.length; i++) { System.out.println(a[i]); } } } 结果: 0 1 99 2 3 0 0 0 0 0 3.2 Arrays.copyOf()方法 /** 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。 */ public Object[] toArray() { //elementData:要复制的数组;size:要复制的长度 return Arrays.copyOf(elementData, size); } 个人觉得使用 Arrays.copyOf()方法主要是为了给原有数组扩容,测试代码如下: public class ArrayscopyOfTest { public static void main(String[] args) { int[] a = new int[3]; a[0] = 0; a[1] = 1; a[2] = 2; int[] b = Arrays.copyOf(a, 10); System.out.println("b.length"+b.length); } } 结果: 10 3.3 两者联系和区别 联系: 看两者源代码可以发现 copyOf() 内部实际调用了 System.arraycopy() 方法 区别: arraycopy() 需要目标数组,将原数组拷贝到你自己定义的数组里或者原数组,而且可以选择拷贝的起点和长度以及放入新数组中的位置 copyOf() 是系统自动在内部新建一个数组,并返回该数组。 四 ensureCapacity方法 ArrayList 源码中有一个 ensureCapacity 方法不知道大家注意到没有,这个方法 ArrayList 内部没有被调用过,所以很显然是提供给用户调用的,那么这个方法有什么作用呢? /** 如有必要,增加此 ArrayList 实例的容量,以确保它至少可以容纳由minimum capacity参数指定的元素数。 * * @param minCapacity 所需的最小容量 */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } 最好在 add 大量元素之前用 ensureCapacity 方法,以减少增量从新分配的次数 我们通过下面的代码实际测试以下这个方法的效果: public class EnsureCapacityTest { public static void main(String[] args) { ArrayList<Object> list = new ArrayList<Object>(); final int N = 10000000; long startTime = System.currentTimeMillis(); for (int i = 0; i < N; i++) { list.add(i); } long endTime = System.currentTimeMillis(); System.out.println("使用ensureCapacity方法前:"+(endTime - startTime)); list = new ArrayList<Object>(); long startTime1 = System.currentTimeMillis(); list.ensureCapacity(N); for (int i = 0; i < N; i++) { list.add(i); } long endTime1 = System.currentTimeMillis(); System.out.println("使用ensureCapacity方法后:"+(endTime1 - startTime1)); } } 运行结果: 使用ensureCapacity方法前:4637 使用ensureCapacity方法前:241 通过运行结果,我们可以很明显的看出向 ArrayList 添加大量元素之前最好先使用ensureCapacity 方法,以减少增量从新分配的次数

优秀的个人博客,低调大师

六个方向关于iOS100个面试题,你都会了吗?

常见问题 你昨天/这周学习了什么? 你为什么热衷于软件开发? 你对哪一种控制系统比较熟悉? 是否参与过GitHub项目? 是否参与过GitHub或其他同类型网站的iOS开源项目? 请描述一下你的iOS应用开发流程。 是否熟知CocoaPods?它是什么?如何运行的? 请概括一下你对软件授权的理解,及其对软件开发的影响。 请概括一下你在构建iOS应用时的测试过程。iOS应用如何实现对其他语言、日期格式以及货币单位的支持? 请描述一下Instruments及其作用。 关于iOS技术 请解释一下Handoff是什么,并简述它是如何实现iOS、Mac/网页应用互通的。 iCloud包含了哪些技术与服务? iOS扩展是指?能否列举一些热门或常见的范例? HealthKit是什么? HomeKit是什么? Apple Pay是什么?能否描述一下如何在应用中使用Apple Pay? 请解释一下iOS应用沙盒机制。 VoiceOver是什么?请举例解释一下iOS中的辅助功能(Accessibility)。开发者如何使用这些功能? iOS应用是如何实现后台多任务处理(Multitasking)的? Game Center针对iOS游戏有哪些功能? iBeacons是什么? Cocoa/Cocoa Touch是什么? 请概括一下Core Audio,Core Data以及Core Location各是什么。它们对iOS应用有何意义? 请描述SpriteKit和SceneKit的作用。 Metal是什么? 响应链(Responder Chain)是什么?它是如何发挥作用的? 按钮和其他控制方式对哪些操作做出回应? AppDelegate扮演着什么样的角色? 请解释一下NSUserDefaults。就你而言,你会如何在磁盘中对数组对象进行序列化? 你会如何储存用户的认证信息? 请问何为Keychain服务? 为什么移动设备上的缓存和压缩是不可或缺的? 请解释一下~/Documents,~/Library和~/tmp。 iOS中的~属于什么目录? AirPlay是如何运行的?换做是你,你会如何通过编程提高应用的实用性以及演示效果? 传感器,IO以及WiFi、拨号等连接方式如何在iOS平台上运作?它们有何利用价值?请扼要地谈谈你的观点。 iPad 2,iPad mini 1-3,iPad Retina,iPad Air 2,iPhone 5、5S、6以及6+在硬件性能方面有何差异?这对注重性能的应用有何限制? 关于编程 Cocoa Touch包含什么?不包含什么? 为什么Cocoa Touch的类名称是以两个大写字母开头的? Swift和Objective-C分别是什么?两者相比有何不同之处,又有何联系? 为什么Optional在Swift语言中非常重要? 请解释一下NSError。在Swift中,什么情况下能使用NSError ,什么情况下不能? 请说明如何使用Instancetype及其重要性。 在Swift中,什么时候该用let,什么时候该用var? 为什么map函数必不可少?该在什么情况下使用它? 你会选择什么工具来追踪Bug? 如果在Cocoa中发现一个Bug,你会如何处理? 如果应用的新版本出现了Regression的情况,该如何补救?如何防止用户在使用过程中遇到新的Bug? Objective-C的类是怎么执行的?Objective-C Runtime是如何实现的? iOS是如何提高安全性,保护用户隐私信息的? 应用可以下载并即刻显示数据。如何根据MVC来判断下载的最佳位置? MVC对代码库(Codebase)的设计有何影响? Controller Life-Cycle以及View Life-cycle分别有哪些调试方法? iOS使用的是哪些设计模式(Design Patterns)?你的代码库使用的是哪些设计模式? iOS提供哪些线程?如何充分利用这些线程? 请简要描述一下UIScrollView的执行过程。它是如何响应手势识别(Gesture Recognizer)、多点触控(Multi-Touch)和Run Loop的? 你认为iOS需要添加或改进哪些API? 关于界面 iPhone5、6、6+以及iPad Air 2的屏幕分辨率分别是多少? 分辨率的计算单位是什么? 请解释一下Interface Builder的作用以及NIB文件的概念。 iOS UI的图像储存类型是什么? 请描述一下Storyboard和标准NIB文件的差别。 设备状态栏(Device Status Bar)是什么?高度如何?是否透明?在手机通话或者导航状态下,它是如何显示的? 导航栏(Navigation Bar)是什么?能否拿出你的iPhone,指出你下载的哪些应用运用了导航栏? 选项卡(Tab Bar)和工具栏(Toolbar)分别是什么?两者之间有何共同点和不同点? 表视图(Table View)是什么?集合视图(Collection View)又是什么? 什么时候用“弹出(Popover)”属性最为合适? Split-view Controller是什么? 选取器视图(Picker View)适合存放哪类内容? 应该在什么情况下使用标签、文本域和文本视图? 分段控件(Segmented Control)的作用是什么? 模态视图(Modal View)是什么? iOS通知属于什么类型? 关于设计 iOS应用图标是指什么?请尽可能详细地描述一下。 最小尺寸和最大尺寸的应用图标分别是什么样子的? 应用图标能否包含透明的部分? Newsstand的图标与常规应用有何不同? 请解释一下启动画面(Launch Images)。 自动布局(Auto Layout)的作用是什么?请概括一下它是如何运行的。 设计软件时为什么要加上动画? 请描述一下软件设计中的交互和Feedback有什么作用。 设计iPhone和iPad应用时,应分别考虑哪些因素? 请描述一下原型设计对于软件开发的意义。其作用是什么? 关于App Store 应用内购买(In-App Purchases)是怎么回事?IAP能够为用户带来哪些新体验? 你是否在App Store上发布过应用?能否概括一下过程? iTunes Connect是什么? Provisioning Profiles是指? App ID是什么? iOS的开发和发布签名证书有何异同? 如何使用TestFlight?通过Ad-hoc发布应用的话,该如何使用UUID? 应何时验证购买收据? 发布iAds(苹果平台广告)有哪些要求? 趣味问答 最近有没有开发什么好玩的东西?你最引以为豪的作品是什么? 谈一谈你常用的开发工具都有哪些优势? 你最敬佩的独立Mac或者iOS应用开发者是谁? 最喜欢什么项目?哪种类型的? 你觉得Xcode有哪些需要改进的地方? iOS上你最喜欢哪些API? 是否有最中意的错误报告? 你最爱以哪种方式来检验一项新技术是否好用? 为什么词典被称作Dictionaries,而不是HashTable或HashMap?

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册