Java Code Examples for java.util.ListIterator#remove()
The following examples show how to use
java.util.ListIterator#remove() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AuthCacheImpl.java From jdk8u-jdk with GNU General Public License v2.0 | 6 votes |
public synchronized void remove (String pkey, AuthCacheValue entry) { LinkedList<AuthCacheValue> list = hashtable.get (pkey); if (list == null) { return; } if (entry == null) { list.clear(); return; } ListIterator<AuthCacheValue> iter = list.listIterator (); while (iter.hasNext()) { AuthenticationInfo inf = (AuthenticationInfo)iter.next(); if (entry.equals(inf)) { iter.remove (); } } }
Example 2
Source File: TestList.java From jtransc with Apache License 2.0 | 6 votes |
/** * Tests remove on list iterator is correct. */ public void testListListIteratorNextRemoveNext() { if (isRemoveSupported() == false) return; resetFull(); if (collection.size() < 4) return; ListIterator it = getList().listIterator(); Object zero = it.next(); Object one = it.next(); Object two = it.next(); assertEquals(zero, getList().get(0)); assertEquals(one, getList().get(1)); assertEquals(two, getList().get(2)); Object three = getList().get(3); it.remove(); // removed element at index 2 (two) assertEquals(zero, getList().get(0)); assertEquals(one, getList().get(1)); Object three2 = it.next(); // do next after remove assertEquals(three, three2); assertEquals(collection.size() > 3, it.hasNext()); assertEquals(true, it.hasPrevious()); }
Example 3
Source File: ListRVAdapter.java From tenor-android-core with Apache License 2.0 | 6 votes |
public synchronized void threadSafeRemove(@NonNull final IThreadSafeConditions<T> conditions) { if (conditions == null) { throw new IllegalArgumentException("conditions cannot be null"); } /* * Remove everything except PivotsRV * * Use iterator to avoid ConcurrentModificationException */ ListIterator<T> iterator = getList().listIterator(); final Stack<Integer> positions = new Stack<>(); int position; T item; while (iterator.hasNext()) { position = iterator.nextIndex(); item = iterator.next(); if (conditions.removeIf(item)) { iterator.remove(); positions.push(position); } } conditions.onItemsRemoved(positions); }
Example 4
Source File: JobQueue.java From deltachat-android with GNU General Public License v3.0 | 6 votes |
private Job getNextAvailableJob() { if (jobQueue.isEmpty()) return null; ListIterator<Job> iterator = jobQueue.listIterator(); while (iterator.hasNext()) { Job job = iterator.next(); if (job.isRequirementsMet() && isGroupIdAvailable(job)) { iterator.remove(); setGroupIdUnavailable(job); return job; } } return null; }
Example 5
Source File: ActivityStack.java From container with GNU General Public License v3.0 | 6 votes |
/** * App started in VA may be removed in OverView screen, then AMS.removeTask * will be invoked, all data struct about the task in AMS are released, * while the client's process is still alive. So remove related data in VA * as well. A new TaskRecord will be recreated in `onActivityCreated` */ private void optimizeTasksLocked() { // noinspection deprecation ArrayList<ActivityManager.RecentTaskInfo> recentTask = new ArrayList<>(mAM.getRecentTasks(Integer.MAX_VALUE, ActivityManager.RECENT_WITH_EXCLUDED | ActivityManager.RECENT_IGNORE_UNAVAILABLE)); int N = mHistory.size(); while (N-- > 0) { TaskRecord task = mHistory.valueAt(N); ListIterator<ActivityManager.RecentTaskInfo> iterator = recentTask.listIterator(); boolean taskAlive = false; while (iterator.hasNext()) { ActivityManager.RecentTaskInfo info = iterator.next(); if (info.id == task.taskId) { taskAlive = true; iterator.remove(); break; } } if (!taskAlive) { mHistory.removeAt(N); } } }
Example 6
Source File: DefaultKeyboardFocusManager.java From jdk-1.7-annotated with Apache License 2.0 | 5 votes |
/** * Releases for normal dispatching to the current focus owner all * KeyEvents which were enqueued because of a call to * <code>enqueueKeyEvents</code> with the same timestamp and Component. * If the given timestamp is less than zero, the outstanding enqueue * request for the given Component with the <b>oldest</b> timestamp (if * any) should be cancelled. * * @param after the timestamp specified in the call to * <code>enqueueKeyEvents</code>, or any value < 0 * @param untilFocused the Component specified in the call to * <code>enqueueKeyEvents</code> * @see #enqueueKeyEvents * @see #discardKeyEvents */ protected synchronized void dequeueKeyEvents(long after, Component untilFocused) { if (untilFocused == null) { return; } focusLog.finer("Dequeue at {0} for {1}", after, untilFocused); TypeAheadMarker marker; ListIterator iter = typeAheadMarkers.listIterator ((after >= 0) ? typeAheadMarkers.size() : 0); if (after < 0) { while (iter.hasNext()) { marker = (TypeAheadMarker)iter.next(); if (marker.untilFocused == untilFocused) { iter.remove(); return; } } } else { while (iter.hasPrevious()) { marker = (TypeAheadMarker)iter.previous(); if (marker.untilFocused == untilFocused && marker.after == after) { iter.remove(); return; } } } }
Example 7
Source File: LdapGroupAuthTest.java From gemfirexd-oss with Apache License 2.0 | 5 votes |
private void checkGrantees(GranteeIterator granteeIter, String... expectedGrantees) { LinkedList<String> expected = new LinkedList<String>( Arrays.asList(expectedGrantees)); while (granteeIter.hasNext()) { String grantee = granteeIter.next(); String group = granteeIter.getCurrentLdapGroup(); ListIterator<String> expectedIter = expected.listIterator(); while (expectedIter.hasNext()) { String expectedGrantee = expectedIter.next(); String expectedGroup = expectedIter.next(); if (grantee.equals(expectedGrantee) && ArrayUtils.objectEquals( granteeIter.getCurrentLdapGroup(), expectedGroup)) { // indicates match found grantee = null; expectedIter.previous(); expectedIter.previous(); expectedIter.remove(); expectedIter.next(); expectedIter.remove(); break; } } if (grantee != null) { Assert.fail("Failed to find grantee=" + grantee + " group=" + group + " among expected: " + expected); } } if (!expected.isEmpty()) { Assert.fail("No match found for expected elements: " + expected); } }
Example 8
Source File: FilterUtil.java From smallrye-open-api with Apache License 2.0 | 5 votes |
/** * Filters the given model. * * @param filter * @param models */ private static void filterTags(OASFilter filter, List<Tag> models) { if (models != null) { ListIterator<Tag> iterator = models.listIterator(); while (iterator.hasNext()) { Tag model = iterator.next(); model = filter.filterTag(model); if (model == null) { iterator.remove(); } } } }
Example 9
Source File: DefaultKeyboardFocusManager.java From jdk8u-jdk with GNU General Public License v2.0 | 5 votes |
/** * Releases for normal dispatching to the current focus owner all * KeyEvents which were enqueued because of a call to * <code>enqueueKeyEvents</code> with the same timestamp and Component. * If the given timestamp is less than zero, the outstanding enqueue * request for the given Component with the <b>oldest</b> timestamp (if * any) should be cancelled. * * @param after the timestamp specified in the call to * <code>enqueueKeyEvents</code>, or any value < 0 * @param untilFocused the Component specified in the call to * <code>enqueueKeyEvents</code> * @see #enqueueKeyEvents * @see #discardKeyEvents */ protected synchronized void dequeueKeyEvents(long after, Component untilFocused) { if (untilFocused == null) { return; } if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { focusLog.finer("Dequeue at {0} for {1}", after, untilFocused); } TypeAheadMarker marker; ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator ((after >= 0) ? typeAheadMarkers.size() : 0); if (after < 0) { while (iter.hasNext()) { marker = iter.next(); if (marker.untilFocused == untilFocused) { iter.remove(); return; } } } else { while (iter.hasPrevious()) { marker = iter.previous(); if (marker.untilFocused == untilFocused && marker.after == after) { iter.remove(); return; } } } }
Example 10
Source File: BaseRecyclerAdapter.java From okhttp-OkGo with Apache License 2.0 | 5 votes |
/** 移除一条数据 */ public void removeItem(T item) { int position = 0; ListIterator<T> iterator = mDatas.listIterator(); while (iterator.hasNext()) { T next = iterator.next(); if (next == item) { iterator.remove(); notifyItemRemoved(position); } position++; } }
Example 11
Source File: CallActivity.java From restcomm-android-sdk with GNU Affero General Public License v3.0 | 5 votes |
private boolean havePermissions(ArrayList<String> permissions) { boolean allGranted = true; ListIterator<String> it = permissions.listIterator(); while (it.hasNext()) { if (ActivityCompat.checkSelfPermission(this, it.next()) != PackageManager.PERMISSION_GRANTED) { allGranted = false; } else { // permission granted, remove it from permissions it.remove(); } } return allGranted; }
Example 12
Source File: Remove.java From jdk8u-jdk with GNU General Public License v2.0 | 5 votes |
public static void main(String[] args) { LinkedList list = new LinkedList(); ListIterator e = list.listIterator(); Object o = new Integer(1); e.add(o); e.previous(); e.next(); e.remove(); e.add(o); if (!o.equals(list.get(0))) throw new RuntimeException("LinkedList ListIterator remove failed."); }
Example 13
Source File: PersistentIndex.java From ambry with Apache License 2.0 | 5 votes |
/** * Filter out the put entries and only get the delete entries. * @param messageEntries The message entry list from which only delete entries have to be returned. */ private void filterDeleteEntries(List<MessageInfo> messageEntries) { ListIterator<MessageInfo> messageEntriesIterator = messageEntries.listIterator(); /* Note: Ideally we should also filter out duplicate delete entries here. However, due to past bugs, there could be multiple delete entries in the index for the same blob. At the cost of possibly duplicating the effort for those rare cases, we ensure as much deletes are covered as possible. */ while (messageEntriesIterator.hasNext()) { if (!messageEntriesIterator.next().isDeleted()) { messageEntriesIterator.remove(); } } }
Example 14
Source File: DocumentProcessingHandlerTransformingMessagesTestCase.java From vespa with Apache License 2.0 | 5 votes |
@Override public Progress process(Processing processing) { ListIterator<DocumentOperation> it = processing.getDocumentOperations().listIterator(); while (it.hasNext()) { DocumentOperation op = it.next(); String id = op.getId().toString(); if ("id:nodocstatus:foo::put:to:put".equals(id)) { Document doc = ((DocumentPut)op).getDocument(); doc.setFieldValue("foostring", new StringFieldValue("banana")); } else if ("id:nodocstatus:foo::put:to:remove".equals(id)) { it.set(new DocumentRemove(new DocumentId(id))); } else if ("id:nodocstatus:foo::put:to:update".equals(id)) { it.set(new DocumentUpdate(getType(), id)); } else if ("id:nodocstatus:foo::put:to:nothing".equals(id)) { it.remove(); } else if ("id:nodocstatus:foo::remove:to:put".equals(id)) { it.set(new DocumentPut(getType(), op.getId())); } else if ("id:nodocstatus:foo::remove:to:remove".equals(id)) { //nada } else if ("id:nodocstatus:foo::remove:to:update".equals(id)) { it.set(new DocumentUpdate(getType(), id)); } else if ("id:nodocstatus:foo::remove:to:nothing".equals(id)) { it.remove(); } else if ("id:nodocstatus:foo::update:to:put".equals(id)) { it.set(new DocumentPut(getType(), op.getId())); } else if ("id:nodocstatus:foo::update:to:remove".equals(id)) { it.set(new DocumentRemove(new DocumentId(id))); } else if ("id:nodocstatus:foo::update:to:update".equals(id)) { //nada } else if ("id:nodocstatus:foo::update:to:nothing".equals(id)) { it.remove(); } else if ("id:12345:6789:multiop:nodocstatus:keep:this".equals(id)) { //nada } } return Progress.DONE; }
Example 15
Source File: ICUtil.java From swift-t with Apache License 2.0 | 5 votes |
public static void replaceVarsInList(Map<Var, Arg> replacements, List<Var> vars, boolean removeDupes, boolean removeMapped) { // Remove new duplicates ArrayList<Var> alreadySeen = null; if (removeDupes) { alreadySeen = new ArrayList<Var>(vars.size()); } ListIterator<Var> it = vars.listIterator(); while (it.hasNext()) { Var v = it.next(); if (replacements.containsKey(v)) { Arg oa = replacements.get(v); if (oa.isVar()) { if (removeDupes && alreadySeen.contains(oa.getVar())) { it.remove(); } else { it.set(oa.getVar()); if (removeDupes) { alreadySeen.add(oa.getVar()); } } } } else { if (removeDupes) { if (alreadySeen.contains(v)) { it.remove(); } else { alreadySeen.add(v); } } } } }
Example 16
Source File: ValueNumber.java From swift-t with Apache License 2.0 | 4 votes |
/** * Inline from bottom-up * @param mainBlock * @param cong */ private void inlinePass(GlobalConstants consts, Block block, Map<Block, Congruences> cong) { Congruences blockState = cong.get(block); if (blockState == null) { // Dead code return; } if (logger.isTraceEnabled()) { logger.trace("======================================="); logger.trace("Inlining statements on block " + System.identityHashCode(block) + ": " + block.getType()); blockState.printTraceInfo(logger, consts); } // Use original statement count from when block was constructed int origStmtCount = block.getStatements().size(); ListIterator<Statement> stmtIt = block.statementIterator(); while (stmtIt.hasNext()) { Statement stmt = stmtIt.next(); if (stmt.type() == StatementType.CONDITIONAL) { // First recurse tryInlineConditional(consts, block, stmtIt, stmt.conditional(), cong); } else { assert(stmt.type() == StatementType.INSTRUCTION); // Leave instructions alone } } // Block state will reflect closed vars as of end of block Set<Var> closedVars; Set<Var> recClosedVars; if (finalizedVarEnabled) { recClosedVars = blockState.getRecursivelyClosed(origStmtCount); closedVars = blockState.getClosed(origStmtCount); } else { recClosedVars = Collections.emptySet(); closedVars = Collections.emptySet(); } if (logger.isTraceEnabled()) { logger.trace("======================================="); logger.trace("Inlining continuations on block " + System.identityHashCode(block) + ": " + block.getType()); blockState.printTraceInfo(logger, consts); } ListIterator<Continuation> contIt = block.continuationIterator(); while (contIt.hasNext()) { Continuation cont = contIt.next(); // First recurse inlinePassRecurse(consts, cont, cong); if (logger.isTraceEnabled()) { logger.trace("Return to block " + System.identityHashCode(block) + " checking " + cont.getType()); } // Then try to inline if (cont.isNoop()) { logger.trace("Removed noop continuation " + cont.getType()); contIt.remove(); } else if (tryInlineContinuation(block, cont, contIt, closedVars, recClosedVars)) { // Success! Will now iterate over rest logger.trace("Inlined continuation " + cont.getType()); } } }
Example 17
Source File: GfxdDDLRegionQueue.java From gemfirexd-oss with Apache License 2.0 | 4 votes |
/** * Get the DDL queue after pre-processing like pushing system procedures, jar * procedures at the start, removing local DDLs etc. */ public List<GfxdDDLQueueEntry> getPreprocessedDDLQueue( final List<GfxdDDLQueueEntry> currentQueue, final Map<DDLConflatable, DDLConflatable> skipRegionInit, String currentSchema, TObjectIntHashMap pre11TableSchemaVer, boolean traceConflation) { // push all system procedures at the start of queue since they may change // the behaviour of the system which can be required for DDLs etc. final ArrayList<GfxdDDLQueueEntry> preprocessedQueue = new ArrayList<GfxdDDLQueueEntry>(); ListIterator<GfxdDDLQueueEntry> iter = currentQueue.listIterator(); GfxdDDLPreprocess preprocessMsg; if (currentSchema == null) { currentSchema = SchemaDescriptor.STD_DEFAULT_SCHEMA_NAME; } while (iter.hasNext()) { final GfxdDDLQueueEntry entry = iter.next(); final Object qVal = entry.getValue(); if (qVal instanceof ReplayableConflatable) { // remove from queue if this object is marked to be skipped // in local execution if (((ReplayableConflatable)qVal).skipInLocalExecution()) { iter.remove(); continue; } } // system/jar procedures should be executed at the start if (qVal instanceof GfxdDDLPreprocess && (preprocessMsg = (GfxdDDLPreprocess)qVal).preprocess()) { if (pre11TableSchemaVer != null && preprocessMsg instanceof GfxdSystemProcedureMessage) { GfxdSystemProcedureMessage m = (GfxdSystemProcedureMessage)qVal; // check for persisted PRE11_RECOVERY_SCHEMA_VERSIONs if (m.getSysProcMethod() == GfxdSystemProcedureMessage .SysProcMethod.setDatabaseProperty) { Object[] params = m.getParameters(); String key = (String)params[0]; if (key != null && key.startsWith( GfxdConstants.PRE11_RECOVERY_SCHEMA_VERSION)) { pre11TableSchemaVer.put(key .substring(GfxdConstants.PRE11_RECOVERY_SCHEMA_VERSION .length()), Integer.parseInt((String)params[1])); } } } preprocessedQueue.add(entry); iter.remove(); } // also check if region intialization should be skipped for // any of the regions due to ALTER TABLE (#44280) else if (qVal instanceof DDLConflatable) { final DDLConflatable ddl = (DDLConflatable)qVal; if (skipRegionInit == null) { // need to add explicit "CREATE SCHEMA" DDLs for this case if the // schema changes String newSchema = ddl.getCurrentSchema(); if (newSchema == null) { newSchema = SchemaDescriptor.STD_DEFAULT_SCHEMA_NAME; } if (!currentSchema.equals(newSchema)) { DDLConflatable schemaDDL = new DDLConflatable("SET SCHEMA " + newSchema, newSchema, new CreateSchemaConstantAction( newSchema, null), null, null, 0, true); final QueueValue qValue = new QueueValue(0L, new RegionValue( schemaDDL, 0L)); iter.add(qValue); } currentSchema = newSchema; } else if (ddl.shouldDelayRegionInitialization()) { final ArrayList<QueueValue> conflatedItems = new ArrayList<QueueValue>(5); if (conflate(ddl, ddl, false, conflatedItems)) { for (QueueValue confItem : conflatedItems) { Object confVal = confItem.getValue(); DDLConflatable createDDL; if (confVal instanceof DDLConflatable && (createDDL = (DDLConflatable)confVal).isCreateTable()) { // update the mapping for CREATE TABLE to this ALTER skipRegionInit.put(createDDL, ddl); if (traceConflation) { SanityManager.DEBUG_PRINT(GfxdConstants.TRACE_CONFLATION, "FabricDatabase: delaying initializing [" + confVal + "] for DDL [" + ddl + ']'); } // expect only one CREATE TABLE at max, so break now break; } } } } } } preprocessedQueue.addAll(currentQueue); return preprocessedQueue; }
Example 18
Source File: StormSchedulerImpl.java From storm with Apache License 2.0 | 4 votes |
/** * Schedule function looks in the "mesosWorkerSlotMap" to determine which topology owns the particular * WorkerSlot and assigns the executors accordingly. */ @Override public void schedule(Topologies topologies, Cluster cluster) { List<WorkerSlot> workerSlots = cluster.getAvailableSlots(); String info = ""; if (!workerSlots.isEmpty()) { info = "Scheduling the following worker slots from cluster.getAvailableSlots: "; List<String> workerSlotsStrings = new ArrayList<String>(); for (WorkerSlot ws : workerSlots) { workerSlotsStrings.add(ws.toString()); } info += String.format("[%s]", StringUtils.join(workerSlotsStrings, ", ")); log.info(info); } Map<String, List<MesosWorkerSlot>> perTopologySlotList = getMesosWorkerSlotPerTopology(workerSlots); if (perTopologySlotList.isEmpty()) { return; } info = "Schedule the per-topology slots:"; for (String topo : perTopologySlotList.keySet()) { List<String> mwsAssignments = new ArrayList<>(); for (MesosWorkerSlot mws : perTopologySlotList.get(topo)) { mwsAssignments.add(mws.getNodeId() + ":" + mws.getPort()); } info += String.format(" {%s, [%s]}", topo, StringUtils.join(mwsAssignments, ", ")); } log.info(info); // So far we know how many MesosSlots each of the topologies have got. Let's assign executors for each of them for (String topologyId : perTopologySlotList.keySet()) { TopologyDetails topologyDetails = topologies.getById(topologyId); List<MesosWorkerSlot> mesosWorkerSlots = perTopologySlotList.get(topologyId); int slotsRequested = topologyDetails.getNumWorkers(); int slotsAssigned = cluster.getAssignedNumWorkers(topologyDetails); int slotsAvailable = mesosWorkerSlots.size(); if (slotsAvailable == 0) { log.warn("No slots found for topology {} while scheduling", topologyId); continue; } log.info("topologyId: {}, slotsRequested: {}, slotsAssigned: {}, slotsAvailable: {}", topologyId, slotsRequested, slotsAssigned, slotsAvailable); List<List<ExecutorDetails>> executorsPerWorkerList = executorsPerWorkerList(cluster, topologyDetails, slotsRequested, slotsAssigned, slotsAvailable); if (executorsPerWorkerList == null || executorsPerWorkerList.isEmpty()) { continue; } info = "schedule: Cluster assignment for " + topologyId + "." + " Requesting " + slotsRequested + " slots, with " + slotsAvailable + " slots available, and " + slotsAssigned + " currently assigned." + " Setting new assignment (node:port, executorsPerWorkerList) as: "; List<String> slotAssignmentStrings = new ArrayList<String>(); ListIterator<List<ExecutorDetails>> iterator = executorsPerWorkerList.listIterator(); while (iterator.hasNext()) { List<ExecutorDetails> executorsPerWorker = iterator.next(); slotAssignmentStrings.add("(" + mesosWorkerSlots.get(0).getNodeId() + ":" + mesosWorkerSlots.get(0).getPort() + ", " + executorsPerWorker.toString() + ")"); iterator.remove(); cluster.assign(mesosWorkerSlots.remove(0), topologyId, executorsPerWorker); } if (slotsAvailable == 0) { info += "[]"; } else { info += StringUtils.join(slotAssignmentStrings, ", "); } log.info(info); } mesosWorkerSlotMap.clear(); }
Example 19
Source File: IteratorDefaults.java From TencentKona-8 with GNU General Public License v2.0 | 4 votes |
public void testOptimizedForEach() throws Exception { final Integer[] data = new Integer[1000 * 1000]; for (int i=0; i < data.length; i++) { data[i] = i; } final List<Integer> source = Arrays.asList(data); final String[] listClasses = { "java.util.ArrayList", "java.util.LinkedList", "java.util.Vector", "java.util.concurrent.CopyOnWriteArrayList" }; final int OFFSET = 3; final List<Integer> target = new ArrayList<>(source); for (final String listClass : listClasses) { final List<Integer> list = (List<Integer>) Class.forName(listClass).newInstance(); list.addAll(source); final ListIterator<Integer> iterator = list.listIterator(); assertFalse(iterator.hasPrevious()); for (int i=0; i < OFFSET; i++) { iterator.next(); } assertTrue(iterator.hasNext()); assertTrue(iterator.hasPrevious()); assertEquals(iterator.nextIndex(), OFFSET); assertEquals(iterator.previousIndex(), OFFSET - 1); iterator.forEachRemaining(e -> { target.set(e, e + 1); }); for (int i=OFFSET; i < data.length; i++) { assertEquals(target.get(i).intValue(), source.get(i)+1); } assertFalse(iterator.hasNext()); assertTrue(iterator.hasPrevious()); assertEquals(iterator.nextIndex(), data.length); assertEquals(iterator.previousIndex(), data.length - 1); // CopyOnWriteArrayList.listIterator().remove() is unsupported if (!"java.util.concurrent.CopyOnWriteArrayList".equals(listClass)) { for (int i = data.length - 1; i >= 0; i--) { iterator.remove(); // must not throw if (i > 0) { iterator.previous(); } } assertTrue(list.isEmpty()); } try { iterator.next(); fail(listClass + " iterator advanced beyond end"); } catch (NoSuchElementException ignore) { } } }
Example 20
Source File: diff_match_patch.java From ctsms with GNU Lesser General Public License v2.1 | 4 votes |
/** * Look for single edits surrounded on both sides by equalities * which can be shifted sideways to align the edit to a word boundary. * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came. * @param diffs LinkedList of Diff objects. */ public void diff_cleanupSemanticLossless(LinkedList<Diff> diffs) { String equality1, edit, equality2; String commonString; int commonOffset; int score, bestScore; String bestEquality1, bestEdit, bestEquality2; // Create a new iterator at the start. ListIterator<Diff> pointer = diffs.listIterator(); Diff prevDiff = pointer.hasNext() ? pointer.next() : null; Diff thisDiff = pointer.hasNext() ? pointer.next() : null; Diff nextDiff = pointer.hasNext() ? pointer.next() : null; // Intentionally ignore the first and last element (don't need checking). while (nextDiff != null) { if (prevDiff.operation == Operation.EQUAL && nextDiff.operation == Operation.EQUAL) { // This is a single edit surrounded by equalities. equality1 = prevDiff.text; edit = thisDiff.text; equality2 = nextDiff.text; // First, shift the edit as far left as possible. commonOffset = diff_commonSuffix(equality1, edit); if (commonOffset != 0) { commonString = edit.substring(edit.length() - commonOffset); equality1 = equality1.substring(0, equality1.length() - commonOffset); edit = commonString + edit.substring(0, edit.length() - commonOffset); equality2 = commonString + equality2; } // Second, step character by character right, looking for the best fit. bestEquality1 = equality1; bestEdit = edit; bestEquality2 = equality2; bestScore = diff_cleanupSemanticScore(equality1, edit) + diff_cleanupSemanticScore(edit, equality2); while (edit.length() != 0 && equality2.length() != 0 && edit.charAt(0) == equality2.charAt(0)) { equality1 += edit.charAt(0); edit = edit.substring(1) + equality2.charAt(0); equality2 = equality2.substring(1); score = diff_cleanupSemanticScore(equality1, edit) + diff_cleanupSemanticScore(edit, equality2); // The >= encourages trailing rather than leading whitespace on edits. if (score >= bestScore) { bestScore = score; bestEquality1 = equality1; bestEdit = edit; bestEquality2 = equality2; } } if (!prevDiff.text.equals(bestEquality1)) { // We have an improvement, save it back to the diff. if (bestEquality1.length() != 0) { prevDiff.text = bestEquality1; } else { pointer.previous(); // Walk past nextDiff. pointer.previous(); // Walk past thisDiff. pointer.previous(); // Walk past prevDiff. pointer.remove(); // Delete prevDiff. pointer.next(); // Walk past thisDiff. pointer.next(); // Walk past nextDiff. } thisDiff.text = bestEdit; if (bestEquality2.length() != 0) { nextDiff.text = bestEquality2; } else { pointer.remove(); // Delete nextDiff. nextDiff = thisDiff; thisDiff = prevDiff; } } } prevDiff = thisDiff; thisDiff = nextDiff; nextDiff = pointer.hasNext() ? pointer.next() : null; } }