Use List.clear() to pay attention to a pit

Suppose there is a case where we have a file file with 10 pieces of data in total. We need to divide four pieces into three batches, that is, the first batch is a b c d, the second batch is e f g h, and the third batch is i j. Therefore, the building owner uses map < integer, List < tssbbody > > to load data. As many batches of data as there are, there are as many key value pairs as there are In the size() of the List, it must be 4 4 2. This understanding is relatively simple, so start to roll up the code:

// Determine how many lines a file file has
	public long getLineNumber(File file) {
		if (file.exists()) {
			try {
				FileReader fileReader = new FileReader(file);
				LineNumberReader lineNumberReader = new LineNumberReader(fileReader);
				lineNumberReader.skip(Long.MAX_VALUE);
				long lines = lineNumberReader.getLineNumber() + 1;
				fileReader.close();
				lineNumberReader.close();
				return lines;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return 0;
	}

	public static void main(String[] args) throws InterruptedException {
		int TD_PileSize = 4;
		File file = new File("E:\\ceshi\\1.txt");
		long lineNumber = new Test().getLineNumber(file);
		int DataTotal = Integer.valueOf(String.valueOf(lineNumber));
		// How many batches to get data with features
		int pageCount = (int) Math.ceil((double) DataTotal / TD_PileSize);
		if (DataTotal == 0) {
			System.out.println("No data to push");
		}
		System.out.println("Data to be pushed include" + DataTotal + "strip,branch" + pageCount + "Batch push!");

		InputStreamReader inputReader = null;
		BufferedReader bufferReader = null;
		OutputStream outputStream = null;
		try {
			InputStream inputStream = new FileInputStream(file);
			inputReader = new InputStreamReader(inputStream, "GBK");
			bufferReader = new BufferedReader(inputReader);

			// Read a row
			String line = null;
			Map<Integer, List<TSSBBody>> map = new HashMap<Integer, List<TSSBBody>>();
			List<TSSBBody> listBody = new ArrayList<TSSBBody>();
			if (DataTotal < TD_PileSize | DataTotal == TD_PileSize) {
				while ((line = bufferReader.readLine()) != null) {
					TSSBBody body = null; // In order not to report an error and fill in null, line is actually processed to be converted into an object
					listBody.add(body);
				}
				map.put(0, listBody);
			} else {
				int lineNum = 0;
				int mapNum = 0;
				while ((line = bufferReader.readLine()) != null) {
					lineNum++;
					TSSBBody body = null; // In order not to report an error and fill in null, line is actually processed to be converted into an object
					listBody.add(body);
					if (lineNum % TD_PileSize == 0) {
						mapNum++;
						map.put(mapNum - 1, listBody);
						System.err.println("Before emptying==" + listBody.size());
						listBody.clear();
					}
				}
				map.put(mapNum, listBody);
				System.out.println("mapNum============" + mapNum); //Value =2

				for (Map.Entry<Integer, List<TSSBBody>> a : map.entrySet()) {
					System.err.println("" + a.getKey());
					for (TSSBBody ttBody : a.getValue()) {
						System.err.println(ttBody.toString());
					}
				}
			}

		} catch (IOException e) {
			System.out.println("" + e.getMessage());
		} finally {
			IOCloseUtil.closeAll(outputStream, bufferReader, inputReader);
		}

	}

In fact, the code logic is well understood. When reading 4 lines of multiples, execute the assignment list, then assign it to map, and then clear() reassign it. I think it's OK to understand. In fact, the problem is great. Execute the code trace, and find that the value of map traversal and list is i j. Is it strange??

Let's change the sentence listBody.clear() to:

listBody = null;

listBody = new ArrayList<TSSBBody>();

These two sentences will solve the problem. Then think about it carefully. Isn't that the problem of value reference or object reference in Java?
Value passing (parameter type is basic data type): when a method is called, the actual parameter passes its value to the corresponding formal parameter. The formal parameter just initializes its storage unit content with the value of the actual parameter, which is two different storage units. Therefore, the change of the formal parameter value during the method execution does not affect the value of the actual parameter.

Reference passing (parameter type is reference data type): also known as address passing. When a method is called, the actual parameter is an object (or an array). At this time, the actual parameter and the formal parameter point to the same address. During method execution, the operation of the formal parameter is actually the operation of the real parameter. This result is preserved after the method is finished, so the formal parameter during method execution The change of number will affect the actual parameters.

Therefore, after the clear method is used to clear and then add a map, in fact, all lists are the same object, pointing to the same address, so the value in the list is the element of the last list added, so after clear, the list actually passes through an object from the beginning to the end, and the value of the map is i j. But new is different. If new has multiple objects, changing this list will not affect the other.

186 original articles published, 15 praised, 10000 visitors+
Private letter follow

Tags: Java

Posted on Tue, 14 Jan 2020 22:29:18 -0500 by CoffeeOD