I am reading a text file abc .txt which is tab delimited as shown below
gfh hgh thf
--- --- ---
fgh sji irj
rhf dhh fhf
kji idj ddt
and I am able to read it successfully (for all the columns in the table I have developed a separate pojo along with getters and setters), the advantage is that I can get the value of complete row through its getters.
Now I have to make sure that no column in the table should be null and if any column value is null, then I should throw a new exception, for example ..
gfh hgh thf
--- --- ---
fgh sji irj //row 1
rhf dhh fhf
kji idj ddt
fgq fio //As seen in this row that second column value is null
Now the approach that I am following is that getting the value row wise in a string as shown below
String n = f.getgfh()+f.gethgh()+f.getthf(); //it will contain the contents of the row 1
make a separate method and will pass this string
private boolean validaterow(String f)
{
}
in this method here I am taking the complete row in a string and inside this method I want to break this string in tokens and then further evaluate those tokens for empty or null , if there are then I will return false
Try this,
private boolean validateRow(String f)
{
if(f.getgfh() != null && !f.getgfh().trim().isEmpty() &&
f.gethgh() != null && !f.gethgh().trim().isEmpty() &&
f.getthf() != null && !f.getthf().trim().isEmpty())
{
return true;
}
else
{
return false;
}
}
You can set a null check like in getters
public String gethgh()
{
return (String) ((null == hgh) ? new UserDefinedException() : hgh);
}
here UserDefinedException must be declared as a class
I consider this should work
Why do you pass it to a method?
Use
String row1,row2,row3;
row1=f.getgfh();
row2=f.gethgh();
row3=f.getthf();
You can check for your condition at the time of concatenation.
if(row1==null)
'throw your message
else
row1=""
if(row2==null)
'throw your message
else
row2=""
if(row3==null)
'throw your message
else
row3=""
At last,
String n = row1+row2+row3;
Look at apache string utils library. It might have what you need
Split each line on tab like string.split("\t") and check each token using isEmpty() method of string class.
use StringIsNullOrEmtpy to check if row is valid for every entry of the row
private boolean ValidateRow()
{
return !(StringIsNullOrEmpty((f.getgfh())) ||
StringIsNullOrEmpty((f.gethgh())) ||
StringIsNullOrEmpty((f.getthf()))
);
}
private bool StringIsNullOrEmtpy(string input)
{
return input.isEmpty() || input == null;
}
Let's assume that you have a method getNextValueAndPosPair() which returns the next value of your tsv (tab separate values) file and the position of the last space found after the value read (i.g. a Tab or a Newline).
Then you can validate your input row by chechking that it contains exactly three distinct values separated by a Tab.
Below the implementation:
// A simple general pair class.
class Pair<A, B> {
Pair(A first, A second) {
this.first = first;
this.second = second;
}
public A first() { return first; }
public A second() { return second; }
private final A first;
private final B second;
}
// Returns true if this rows contains 4 distinct values, false otherwise.
private boolean validaterow(String f) {
int pos = 0;
for (int i = 0; i < 3; i++) {
Pair<String, Integer> valueAndPos = getNextValueAndPosPair(f, pos);
String value = valueAndPos.first();
int pos = valueAndPos.second();
if (value.isEmpty()) {
System.err.println("The " + i + "-th value is null.");
return false;
}
pos += 1;
}
return true;
}
// Returns a Pair holding the next tsv value in the row and the position of the delimiter space
private Pair<String, Integer> getNextValueAndPosPair(String f, int start) {
int length = 0;
for (int i = start; i < f.length && !Character.isSpaceChar(f.charAt(i)); i++) length++;
int end = start + length;
String value = f.substring(start, end);
Pair<String, Integer> valueAndPos = new Pair<>(value, end);
return valueAndPos;
}
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I'm trying to code a project that deals with a dumb downed version of an excel sheet. One of the commands I am allowing from the user is assigning a value into specific cells in the format of = . i.e A3 = 72.3%. Once it assigns the value to the cell, it then prints out the entire spreadsheet with the updated changes.
I created different classes to represent different types of cells.
Value Cell is a cell that will contain any double value, Percent Cell is a cell that will contain any percentage value, Text Cell is a cell that will contain text.
While I was trying to run my program, I tried assigning a percentage value to a cell. (A2 = 7.25%)
When the program prints out the entire spreadsheet with the newly assigned A2 percentage cell, it's supposed to truncate the decimal from the percentage and just display 7%.
However, I keep getting this error message
Exception in thread "main" java.lang.NullPointerException
at PercentCell.abbreviatedCellText(PercentCell.java:18)
at Spreadsheet.getGridText(Spreadsheet.java:127)
at Spreadsheet.processCommand(Spreadsheet.java:73)
at TextExcel.main(TextExcel.java:20)
This is part of my code that assigns specific cell types depending on what the user inputs:
//assignment command
} else if (command.contains("=")) {
int eqIndex = command.indexOf("=");
if (!command.substring(eqIndex - 1, eqIndex).equals(" ") || !command.substring(eqIndex + 1, eqIndex + 2).equals(" ")) {
return "Formatting Error: please include a space before and after the ="; //error message
} else {
String[] input = command.split(" ", 3);
SpreadsheetLocation cell = new SpreadsheetLocation(input[0]);
int col = cell.getCol();
int row = cell.getRow();
if (col > COLUMNS || row > ROWS) {
return "Error: cell outside of spreadsheet"; //error message
}
//assigning a textcell
if (input[2].contains("\"")) {
String inputValue = input[2].substring(1, input[2].length() - 1);
TextCell textCell = new TextCell(inputValue);
spreadsheet[row][col] = textCell;
//assigning a percent cell
} else if (input[2].contains("%")) {
PercentCell percentCell = new PercentCell(input[2]);
spreadsheet[row][col] = percentCell;
The percent cell extends super class, Real Cell:
public class RealCell implements Cell {
private String fullText;
public RealCell(String input) {
this.fullText = input;
}
//method that returns the display of the abbreviated cell
public String abbreviatedCellText() {
if (fullText.length() > 10) {
return fullText.substring(0, CELLWIDTH);
} else {
String output = fullText;
while(output.length() < CELLWIDTH) {
output += " ";
}
return output;
}
}
//method that returns the actual value in a real cell
public String fullCellText() {
return fullText;
}
//method that parses the user input into a double
public double getDoubleValue() {
return Double.parseDouble(fullText);
}
}
Here is now the problem part of my code, the Percent Cell class:
public class PercentCell extends RealCell {
private String fullText;
public PercentCell(String input) {
super(input);
}
//method that returns the display of the abbreviated cell, truncating the decimal
public String abbreviatedCellText() {
String value = fullText;
if (value.contains(".")) {
int decIndex = fullText.indexOf(".");
value = value.substring(0, decIndex) + "%";
}
if (value.length() > 10) {
return value.substring(0, CELLWIDTH);
} else {
String output = value;
while(output.length() < CELLWIDTH) {
output += " ";
}
return output;
}
}
//method that parses the user input into a double and returns the percent value into a decimal
public double getDoubleValue() {
double decimal = Double.parseDouble(fullText.substring(0, fullText.length() - 1));
return decimal/100;
}
}
How could I fix this error?
If any clarifications regarding my code are needed (because this is not my entire project) please let me know!
public class PercentCell extends RealCell {
public PercentCell(String input) {
super(input);
}
//method that returns the display of the abbreviated cell, truncating the decimal
public String abbreviatedCellText() {
String value = super.fullCellText();
if (value.contains(".")) {
int decIndex = value.indexOf(".");
value = value.substring(0, decIndex) + "%";
}
if (value.length() > 10) {
return value.substring(0, CELLWIDTH);
} else {
String output = value;
while(output.length() < CELLWIDTH) {
output += " ";
}
return output;
}
}
You used fullText field without giving value and fullText value was always null
I think that was the problem, but let me know please if it helps!
I am trying to write as few lines as possible.
What would be the best way to re-write this in Java? (say we have a "public enum A")
I want to have a way of writing "if something is not null, return it, otherwise, keep going".
I looked into Optional, but Optional.of(...).ifPresent( v -> return v;) does not work, although I wish it did.
Also, if you are asking why I am changing the array inside a for-loop, you can consider that there are multiple initial arrays and I need to test them each.
public A getAValue() {
int[] arr = new int[7];
A returnValue = null;
for (int i=0; i<10; i++) {
//change arr
returnValue = checkSomeCondition(arr);
if (returnValue != null) {
return returnValue;
}
//change arr again
returnValue = checkSomeCondition(arr);
if (returnValue != null) {
return returnValue;
}
//change arr yet again
returnValue = checkSomeCondition(arr);
if (returnValue != null) {
return returnValue;
}
}
return A.UNKNOWN;
}
public A checkSomeCondition(int[] arr) {
if (arr[0]==arr[1]) {
return arr[0]==2 ? A.VALUE_1 : A.VALUE_2;
}
return null;
}
Q: I looked into Optional, but Optional.of(...).ifPresent( v -> return v;) does not work, although I wish it did
Optional::ifPresent works, but different than intended. The return is within the method implementation of the Consumer. Moreover, the Consumer doesn't return anything, the method return type is void.
Q: I am trying to write as few lines as possible.
You achieve what you want with the help of a predefined set of the array suppliers Supplier<int[]> and another for-loop inside the already existing one with a number of iterations the same as a number of conditions.
List<Supplier<int[]>> arrays = new ArrayList<>();
arrays.add(() -> firstArraySource());
arrays.add(() -> secondArraySource());
...
for (...) { // your initial loop
for (Supplier<int[]> arraySupplier: arrays) { // iterate through Suppliers
arr = arraySupplier.get(); // get an array (here is the evaluation)
returnValue = checkSomeCondition(arr); // getting the 'A' value
if (returnValue != null) { // returnin if not null
return returnValue;
}
}
}
The advantage of this approach is that if the sources of arrays are ex. from the database, they won't be called before they are actually needed since they are wrapped in the Suppliers. The calculaiton happens when Supplier::get is called.
Not clear what kind of test your doing or how you are alteringyour arrays but this may be possible:
This should ignore all null return values and only return the first successful test result.
If no successes, a default return object must be supplied.
enum A {
A_VALUE_1, A_VALUE_2, A_UNKNOWN
};
List<Object[]> testArrays = new ArrayList<>();
testArrays.add(new int[] { 1, 2, 3 });
testArrays.add(new int[] { 3, 4, 5 });
testArrays.add(new int[] { 2, 2, 6 });
A res =
// stream the set of arrays
testArrays.stream()
// apply each set in order to the method
// replacing the array under test with the
// method result
.map(arr->checkSomeCondition(arr))
// filter out any null results
.filter(result->result!=null)
// get the first non-null result
.findFirst()
// return the result or some default answer if all
// results were null.
.orElseGet(()->A.A_UNKNOWN);
System.out.println(res);
With the supplied data, prints
A_VALUE_1
Your test method
public A checkSomeCondition(int[] arr) {
if (arr[0] == arr[1]) {
return arr[0] == 2 ? A.A_VALUE_1 : A.A_VALUE_2;
}
return null;
}
The down side is it requires you to supply an array of arrays where subsequent ones are to be used if the previous test fails. You may be able to adapt the concept to your requirements.
Use Optional.ofNullable instead of Optional.of as the latter can't be used for possibly null values. That would work, as well as delegating that task to checkSomeCondition function:
public Optional<A> checkSomeCondition(int[] arr) {
if (arr[0] == arr[1]) {
return Optional.<A>of(arr[0]==2 ? A.VALUE_1 : A.VALUE_2);
}
return Optional.<A>empty();
}
...and then checking the presence of value in getAValue.
The condition can then be checked in a loop, i.e.
public A getAValue() {
int[] arr = new int[7];
final int maxChecks = 10;
Optional<A> returnValue = Optional.<A>empty();
for (int i = 0; i < 10; i++) {
int j = 0;
while (!returnValue.isPresent() && j < maxChecks) {
returnValue = checkSomeCondition(arr);
j++;
}
return returnValue.get();
}
return A.UNKNOWN;
}
HashMap intermediateIdMap = new HashMap(d_idMap.size());
int linkCounter = 0;
for (Iterator it = d_idMap.entrySet().iterator(); it.hasNext(); )
{
Map.Entry me = ((Map.Entry) it.next());
long oldId = (Long) me.getKey();
MapObject mo = d_mc.findMapObject(oldId);
if (mo != null && !isMetaDataType(mo)
&& (IdSpace.isTransient(mo.id()) || d_updateAllIds
|| isNegativeIdUpdate(mo.id())))
{
int transientId = d_idGenerator.getNewId();
I need to get the first transientId when its executed for the very first time and the Id it sets and also the last Id i.e MIN_TRANSIENT and MAX_TRANSIENT
I tried changing the Data Structure to LinkedHashMap which would have given me the 1st and Last element easily but i guess seniors dont want me to change the ds, do you guys help me find an another way
public synchronized int getNewId()
{
// Contract.precondition("Within range", d_currentId <= d_range);
// CMSDL-3988 - recycle/reset the currentId once max reached
if(d_currentId>d_range)
d_currentId=MIN_TRANSIENT;
return d_currentId++;
}
If you need changes for a reason, you should be allowed to do them.
Otherwise, you need some structure around your code such as
boolean firstValueSeen = false;
int firstValue = -1;
for (…) {
…
int transientId = d_idGenerator.getNewId();
firstValueSeen = true;
firstValue = transientId
I been at it for a while I can't figure it out. I am suppose to do a reverse order traversal (right-root-left) and pass the level of the root to the function ShowTree.
What exactly is the level of the root? Is it the height? If yes, this is the code for it:
public int getHeight()
{
return getHeight(_root);
}
private int getHeight (BSTnode top)
{
if (top == null)
return 0;
else
{
int lftHeight = getHeight(top._left);
int rhtHeight = getHeight(top._right);
if (lftHeight > rhtHeight)
return 1 + lftHeight;
else
return 1 + rhtHeight;
}
}
So I assign the value of getHeight to level and pass it to ShowTree. I am suppose to use the level of each node to compute how many spaces to insert in front of the data of each node.
public String ShowTree (int level)
{
return ShowTree(_root,level);
}
private String ShowTree(BSTnode myroot, int level)
{
String result = "";
if (myroot == null)
return "";
else
{
result += ShowTree (myroot._right, level + 1);
result += myroot._data.toStringKey();
result += ShowTree (myroot._left, level + 1);
return result;
}
}
However this diplays the tree like this:
c
b
a
When it should print like this:
c
b
a
In your ShowTree(BSTnode, int) method...
String result = ""; // no extra whitespace
Dont you mean...
String result = " "; //extra whitespace
I am reading a text file abc .txt which is tab delimited as shown below
gfh hgh thf
--- --- ---
fgh sji irj
rhf dhh fhf
kji idj ddt
and I am able to read it successfully (for all the columns in the table I have developed a separate pojo along with getters and setters), the advantage is that I can get the value of complete row through its getters.
Now I have to make sure that no column in the table should be null and if any column value is null, then I should throw a new exception, for example ..
gfh hgh thf
--- --- ---
fgh sji irj //row 1
rhf dhh fhf
kji idj ddt
fgq fio //As seen in this row that second column value is null
Now the approach that I am following is that getting the value row wise in a string as shown below
String n = f.getgfh()+f.gethgh()+f.getthf(); //it will contain the contents of the row 1
make a separate method and will pass this string
private boolean validaterow(String f)
{
}
in this method here I am taking the complete row in a string and inside this method I want to break this string in tokens and then further evaluate those tokens for empty or null , if there are then I will return false
Try this,
private boolean validateRow(String f)
{
if(f.getgfh() != null && !f.getgfh().trim().isEmpty() &&
f.gethgh() != null && !f.gethgh().trim().isEmpty() &&
f.getthf() != null && !f.getthf().trim().isEmpty())
{
return true;
}
else
{
return false;
}
}
You can set a null check like in getters
public String gethgh()
{
return (String) ((null == hgh) ? new UserDefinedException() : hgh);
}
here UserDefinedException must be declared as a class
I consider this should work
Why do you pass it to a method?
Use
String row1,row2,row3;
row1=f.getgfh();
row2=f.gethgh();
row3=f.getthf();
You can check for your condition at the time of concatenation.
if(row1==null)
'throw your message
else
row1=""
if(row2==null)
'throw your message
else
row2=""
if(row3==null)
'throw your message
else
row3=""
At last,
String n = row1+row2+row3;
Look at apache string utils library. It might have what you need
Split each line on tab like string.split("\t") and check each token using isEmpty() method of string class.
use StringIsNullOrEmtpy to check if row is valid for every entry of the row
private boolean ValidateRow()
{
return !(StringIsNullOrEmpty((f.getgfh())) ||
StringIsNullOrEmpty((f.gethgh())) ||
StringIsNullOrEmpty((f.getthf()))
);
}
private bool StringIsNullOrEmtpy(string input)
{
return input.isEmpty() || input == null;
}
Let's assume that you have a method getNextValueAndPosPair() which returns the next value of your tsv (tab separate values) file and the position of the last space found after the value read (i.g. a Tab or a Newline).
Then you can validate your input row by chechking that it contains exactly three distinct values separated by a Tab.
Below the implementation:
// A simple general pair class.
class Pair<A, B> {
Pair(A first, A second) {
this.first = first;
this.second = second;
}
public A first() { return first; }
public A second() { return second; }
private final A first;
private final B second;
}
// Returns true if this rows contains 4 distinct values, false otherwise.
private boolean validaterow(String f) {
int pos = 0;
for (int i = 0; i < 3; i++) {
Pair<String, Integer> valueAndPos = getNextValueAndPosPair(f, pos);
String value = valueAndPos.first();
int pos = valueAndPos.second();
if (value.isEmpty()) {
System.err.println("The " + i + "-th value is null.");
return false;
}
pos += 1;
}
return true;
}
// Returns a Pair holding the next tsv value in the row and the position of the delimiter space
private Pair<String, Integer> getNextValueAndPosPair(String f, int start) {
int length = 0;
for (int i = start; i < f.length && !Character.isSpaceChar(f.charAt(i)); i++) length++;
int end = start + length;
String value = f.substring(start, end);
Pair<String, Integer> valueAndPos = new Pair<>(value, end);
return valueAndPos;
}