Issue with returning all values - java

I am having trouble trying to return all the values in my Register class. Currently it only returns BLOGGS, J but should return JONES, F and SINGH, N also. Thank you in advance.
public static String execute(Register reg, Name n) {
reg.removeName(1);
reg.addName(n);
for (Name nm : reg) {
if(nm.getFamilyName().length() >= 5) {
return (nm.getFamilyName().toUpperCase() + ", " + nm.getFirstName().charAt(0) + "\n");
}
return null;
}
}
Here is the test code for the jUnit test
#Test
public void testExecute() {
Register r = new Register();
r.addName(new Name("Joe", "Bloggs"));
r.addName(new Name("Fred", "Jones"));
r.addName(new Name("Nila", "Singh"));
String result = RegisterApp.execute(r, new Name("Cassie", "Downturn"));
String expectedResult = "BLOGGS, J\nSINGH, N\nDOWNTURN, C\n";
assertEquals("The string returned should match the expected result (run 1)", expectedResult, result);
}

As #Carcigenicate already called out, you're returning right away from your for loop.
You could take advantage of stream api here:
public static String execute(Register reg, Name n) {
reg.removeName(1);
reg.addName(n);
return
reg.stream()
.filter(nm -> nm.getFamilyName().length() >= 5)
.map(nm -> nm.getFamilyName().toUpperCase() + ", " + nm.getFirstName().charAt(0) + "\n")
.collect(Collectors.joining());
}

Related

Trying to update a CompletableFuture variable but get error : local variables referenced from a lambda expression must be final or effectively final

public CompletableFuture<String> description() {
CompletableFuture<String> result = CompletableFuture
.supplyAsync(() -> "Search for: " + this.stop + " <-> " + name + ":\n")
.thenApply(x -> x += "From " + this.stop + "\n");
CompletableFuture<Void> temp = services.thenAccept(x -> {
for (BusService service : x.keySet()) {
CompletableFuture<Set<BusStop>> stops = x.get(service);
result = result.thenApply(y -> y += describeService(service, stops));
}
});
return result;
}
public CompletableFuture<String> describeService(BusService service,
CompletableFuture<Set<BusStop>> stops) {
return stops.thenApply(x -> {
if (x.isEmpty()) {
return "";
}
return x.stream()
.filter(stop -> stop != this.stop)
.reduce("- Can take " + service + " to:\n",
(str, stop) -> str += " - " + stop + "\n",
(str1, str2) -> str1 + str2);
});
}
I was trying to update the result in the forloop in description(), since result.thenApply() results in a new CompletableFuture instance, I need to reassign it to a new variable in order to update result, but i am not very sure how
You don't need to reassign it to a new variable, and you shouldn't. Combine the futures instead.
return services.thenCombine(result, (x, y) -> {
for (BusService service : x.keySet()) {
CompletableFuture<Set<BusStop>> stops = x.get(service);
y += describeService(service, stops);
}
return y;
});

How to improve a cumbersome comparison of 2 objects' fields

We have a program that compares thousands of pairs of Students by checking each field of the Student and counting the diffs:
class Student{
String name;
String address;
String biologyCourse;
.....
// about 100 other fields
}
And the counter POJO class:
class Counters{
long bothStudentsHaveName;
long onlyLeftHasName;
long onlyRightHasName;
......
// number of fields in Student * 3 (both, only left, only right)
}
Our compare function accepts 2 students plus the counters object and needs to scan the fields and update the relevant counters:
public void compareStudents(Student left, Student right, Counters counters){
if (!StringUtils.isEmpty(left.name) && !StringUtils.isEmpty(right.name) ){
counters.bothStudentsHaveName++;
} else if (StringUtils.isEmpty(left.name) && !StringUtils.isEmpty(right.name)){
counters.onlyRightHasName++;
} else if (!StringUtils.isEmpty(left.name) && StringUtils.isEmpty(right.name))){
counters.onlyLeftHasName++;
}
/// and now??
}
At this point, we can add 100s more triplets of if/else like the above - but we believe there should be a much easier way to do that.
Reflection can be an option or maybe X dimensions arrays, but can we somehow write the code so the comparison and counting will be much more generic?
I have solved your problem with one single loop. But here I'm assuming that naming convention for all the fields will be the same as described in your question. Here I am dynamically accessing the Student fields and updating Counter fields accordingly. Here is the complete solution:
Solution Class:
public class Solution {
public void compareStudents(Student left, Student right, Counter counter) throws Exception {
for (Field field : Student.class.getDeclaredFields()) {
Object leftValue = field.get(left);
Object rightValue = field.get(right);
String fieldName = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
if(leftValue != null && rightValue != null) {
Field counterField = Counter.class.getDeclaredField("bothStudentsHave" + fieldName);
counterField.set(counter, (long) counterField.get(counter) + 1);
} else if (leftValue != null) {
Field counterField = Counter.class.getDeclaredField("onlyLeftHas" + fieldName);
counterField.set(counter, (long) counterField.get(counter) + 1);
} else if (rightValue != null) {
Field counterField = Counter.class.getDeclaredField("onlyRightHas" + fieldName);
counterField.set(counter, (long) counterField.get(counter) + 1);
}
}
}
}
Student Class:
class Student {
String name;
String address;
String biologyCourse;
}
Counter Class:
class Counter {
// name
long bothStudentsHaveName;
long onlyLeftHasName;
long onlyRightHasName;
// address
long bothStudentsHaveAddress;
long onlyLeftHasAddress;
long onlyRightHasAddress;
// biologyCourse
long bothStudentsHaveBiologyCourse;
long onlyLeftHasBiologyCourse;
long onlyRightHasBiologyCourse;
// ... and so on
#Override
public String toString() {
return "Counter{" + "\n" +
"\tbothStudentsHaveName = " + bothStudentsHaveName + "\n" +
"\t, onlyLeftHasName = " + onlyLeftHasName + "\n" +
"\t, onlyRightHasName = " + onlyRightHasName + "\n" +
"\t, bothStudentsHaveAddress = " + bothStudentsHaveAddress + "\n" +
"\t, onlyLeftHasAddress = " + onlyLeftHasAddress + "\n" +
"\t, onlyRightHasAddress = " + onlyRightHasAddress + "\n" +
"\t, bothStudentsHaveBiologyCourse = " + bothStudentsHaveBiologyCourse + "\n" +
"\t, onlyLeftHasBiologyCourse = " + onlyLeftHasBiologyCourse + "\n" +
"\t, onlyRightHasBiologyCourse = " + onlyRightHasBiologyCourse + "\n" +
'}';
}
}
Tester Class:
public class Tester {
public static void main(String[] args) throws Exception {
// Creating Dummy Variables
Student student1 = new Student();
student1.name = "Test";
student1.biologyCourse = "Yes";
Student student2 = new Student();
student2.name = "Test1";
student2.address = "abc street";
Counter counter = new Counter();
// Comparing Students
Solution solution = new Solution();
solution.compareStudents(student1, student2, counter);
// Printing Counter
System.out.println(counter);
}
}
Output:
Counter{
bothStudentsHaveName = 1
, onlyLeftHasName = 0
, onlyRightHasName = 0
, bothStudentsHaveAddress = 0
, onlyLeftHasAddress = 0
, onlyRightHasAddress = 1
, bothStudentsHaveBiologyCourse = 0
, onlyLeftHasBiologyCourse = 1
, onlyRightHasBiologyCourse = 0
}
If you keep repreating the same basic pattern of fields, then consider extracting that into a class. For example introduce a FieldComparison class that looks a little like this:
public class FieldComparisonCounter {
public int bothHave;
public int onlyLeftHas;
public int onlyRightHas;
// constructor, getters, setters left as an exercise for the reader
}
Then have a Map<String,FieldComparisonCounter> counters somewhere and a method like this:
public void compareField(String fieldName, String leftValue, String rightValue) {
FieldComparisonCounter counter = counters.get(fieldName);
if (counter == null) {
counter = new FieldComparisonCounter();
counters.put(fieldName, counter);
}
boolean leftHas = !StringUtils.isEmpty(leftValue);
boolean rightHas = !StringUtils.isEmpty(rightValue);
if (leftHas && rightHas) {
counter.bothHave++;
} else if (leftHas) {
counter.onlyLeftHas++;
} else if (rightHas) {
counter.onlyRightHas++;
}
}
Then adding a new field comparison is as simple as calling
compareField("name", left.name, right.name);

Convert java List to object using collection -Stream

From the method List> method() i get the output like this with 3 elements
[123456, 10, 03-JAN-16]
[956233, 20, 03-JAN-16]
[254656, 30, 03-JAN-16]
[455556, 40, 04-JAN-16]
[548566, 50, 03-JAN-16]
[215663, 60, 03-JAN-16]
I need to store the above result in a pojo class name 'ClassName' which has the following columns col1, col2 and col3, So I try to run the following code as
public void method() {
try {
List<List<String>> list = testDAO.methodName();
List<ClassName> className= new ArrayList<ClassName>();
for (Iterator<List<String>> iterator = list.iterator(); iterator.hasNext();) {
List<String> list2 = (List<String>) iterator.next();
int i = 0;
ClassName className= new ClassName ();
for (Iterator<String> iterator2 = list2.iterator(); iterator2.hasNext();) {
String string = (String) iterator2.next();
/* System.out.println(string); */
if (i == 0)
className.setCol1(string);
else if (i == 1)
className.setCol2(Long.parseLong(string));
else if (i == 2)
className.setCol3(string);
i++;
}
odhs.add(className);
System.out.println(className);
// System.out.println(className.col2());
// System.out.println(className.col3());
}
// System.out.println("Total size: "+ odhs.size());
} catch (Exception e) {
e.printStackTrace();
}
}
But i got the output as
com.project.model.ClassName#61af1510
com.project.model.ClassName#37af1f93
com.project.model.ClassName#778d82e9
com.project.model.ClassName#408e96d9
com.project.model.ClassName#59901c4d
com.project.model.ClassName#168cd36b
com.project.model.ClassName#d8d9199
com.project.model.ClassName#3901f6af
Please provide a solution to save the datas in the POJO class 'ClassName'
Your class Odh must override the toString method.
On your Odh class you have to override toString method.
#Override
public String toString ( )
{
return "Odh [firstAttribute=" + firstAttribute + ", secondAttribute=" + secondAttribute + "]";
}
Override Odh's toString method.
Assuming the names of your parameters are dist_id,pv and post_date and all are of String types
#Override
public String toString(){
return getClass().getSimpleName() + "[dist_id=" + dist_id + ", pv=" + pv + ", post_date=" + post_date + "]";
}
That would allow you to print
Odh[dist_id=123456, pv=10, post_date=03-JAN-16]

Java indexing error by increasing the frequency

I have a problem to increase frequency that the word occurs in each file,
I tested into 3 equal files and obtained different results in each.
Example: Each file the word "program" occurs 13 times
but the output I have is:
*the word in the search field as this "programa" and not program because of stemming function
[program]
----------------
Doc: site1.html Freq: 21
Doc: site2.html Freq: 11
Doc: site3.html Freq: 1
none of the outputs are correct.
The output had to be:
[program]
----------------
Doc: site1.html Freq: 13
Doc: site2.html Freq: 13
Doc: site3.html Freq: 13
Document class:
public class Documento {
private String docid;
private int frequencia;
public Documento(String docid, int frequencia) {
this.docid = docid;
this.frequencia = frequencia;
}
public String getDocid() {
return docid;
}
public int getFrequencia() {
return frequencia;
}
public void setFrequencia(int frequencia) {
this.frequencia = frequencia;
}
#Override
public boolean equals(Object o) {
if ((o instanceof Documento) && docid == ((Documento) o).docid && frequencia == ((Documento) o).frequencia) {
return true;
}
return false;
}
Function to insert and find document:
public class Dicionario {
public Map<String, List<Documento>> indice = new HashMap<>();
public void InsereDicionario(String palavra, String docid) {
if (!indice.containsKey(palavra)) {
indice.put(palavra, new ArrayList<Documento>());
indice.get(palavra).add(new Documento(docid, 1));
} else {
boolean inserido = false;
List<Documento> lista = indice.get(palavra);
for (int i = 0; i < lista.size(); i++) {
Documento d = lista.get(i);
if (d.getDocid().equals(docid)) {
// indice.get(palavra).add(new Documento(docid, 1));
inserido = true;
} else {
d.setFrequencia(d.getFrequencia() + 1);
}
System.out.println("");
}
if (!inserido) {
indice.get(palavra).add(new Documento(docid, 1));
}
}
}
public String Busca(String palavra) {
String saida = "";
System.out.println("Buscando [" + palavra + "]");
List<Documento> list = new ArrayList();
for (String p : indice.keySet()) {
if (p.equals(palavra)) {
list.addAll(indice.get(p));
for (Documento d : indice.get(p)) {
System.out.println("Doc: " + d.getDocid() + " Freq: " + d.getFrequencia());
saida += "Doc: " + d.getDocid() + " Freq: " + d.getFrequencia() + "".trim() + "\n";
}
}
}
return saida;
}
Function to call Buscar(Search function) in all words.
for (String palavra : query.split(" ")) {
resultado += ("\n[" + palavra + "]\n----------------\n");
resultado += dic.Busca(palavra.trim());
}
Look at this:
if (d.getDocid().equals(docid)) {
// indice.get(palavra).add(new Documento(docid, 1));
inserido = true;
} else {
d.setFrequencia(d.getFrequencia() + 1);
}
If dociid is found in the list -> then do nothning.
Otherwise (a current doc retrieved from the list is not equal to docid) -> then increment the counter.
Swap these operations, or use a negation in the condition.

Java - static constructor

Hey there Stackoverflowers,
I just started programming in Java and encountered a strange problem concerning printing an object. When a new object of type gast is created the user has to enter his or her birthday. This al works fine, however, if I try to print it out I returns 0-0-0. Why is that? By the way, if I create a new datum directly with the parameter constructor it works fine. Wherein lays the problem? I just can't figure it out. I hope you guys can help me out.
Thanks in advance!
public class Datum {
private static String patroon = "\\d{2}-\\d{2}-\\d{4}";
public int dag;
public int maand;
public int jaar;
Datum(int dag, int maand, int jaar) {
System.out.print("constructor: " + dag);
this.dag = dag;
System.out.println(", dag: " + this.dag);
this.maand = maand;
this.jaar = jaar;
}
Datum() {
newDatum();
}
/* */
public static Datum newDatum() {
String input = Opgave5.userInput("Geboortedatum gast");
boolean b = input.matches(patroon);
if (b) {
String[] str = input.split("-");
int dag = Integer.parseInt(str[0]);
int maand = Integer.parseInt(str[1]);
int jaar = Integer.parseInt(str[2]);
Datum datum = new Datum(dag, maand, jaar);
System.out.println(datum);
return datum;
}
else {
return new Datum();
}
}
public String toString() {
return this.dag + "-" + this.maand + "-" + this.jaar;
}
}
Second class:
Gast() {
this.firstName = Opgave5.userInput("Voornaam gast");
this.lastName = Opgave5.userInput("Achternaam gast");
this.geboortedatum = new Datum();
System.out.println("gast: " + this.geboortedatum); // <--- this prints out 0-0-0
}
public String toString() {
return this.firstName + " " + this.lastName + " " + this.geboortedatum;
}
I think you don't understand constructors in Java. You are merely ignoring the result of newDatum() in the constructor. Also, if it did have the expected effect, it might recurse infinitely in the constructor invocation inside newDatum(). Use something like this; allowing newDatum() to edit the instance will work:
Datum() {
newDatum(this);
}
public static void newDatum(Datum instance) {
String input = Opgave5.userInput("Geboortedatum gast");
boolean b = input.matches(patroon);
if (b) {
String[] str = input.split("-");
int dag = Integer.parseInt(str[0]);
int maand = Integer.parseInt(str[1]);
int jaar = Integer.parseInt(str[2]);
instance.dag = dag;
instance.maand = maand;
instance.jaar = jaar;
System.out.println(instance);
}
else {
new Datum();
}
// ^^ Above code may be buggy, see my answer above code
}
This line:
this.geboortedatum = new Datum();
Is using the default constructor. This will set no values. Try to pass the parameters in via constructor like this:
this.geboortedatum = new Datum(1, 2, 3);
If you want to take advantage of the static method you wrote (which is where you ask for user input), then do the following:
this.geboortedatum = Datum.newDatum();

Categories

Resources