I am doing a online course and I have a problem. i do not understand what is wrong with my code. Can you please take a look and give me a hint? I don't get why the last test is not working. When they add the cat in pos 0 to the list, the list should become [cat, ape, dog, zebra], no?
import java.util.ArrayList;
public class ArrayListMethods
{
ArrayList<String> list; //instance variable
/**
* Constructor for objects of class ArrayListMethods
*/
public ArrayListMethods(ArrayList<String> arrayList)
{
// initialise instance variables
list = arrayList;
}
/**
* Determines if the array list is sorted (do not sort)
* When Strings are sorted, they are in alphabetical order
* Use the compareTo method to determine which string comes first
* You can look at the String compareTo method in the Java API
* #return true if the array list is sorted else false.
*/
public boolean isSorted()
{
boolean sorted = true;
// TODO: Determine if the array is sorted.
for (int i = 0; i < list.size() - 1; i++){
if (list.get(i).compareTo(list.get(i + 1)) < 0){
sorted = true;
}
else {
sorted = false;
}
}
return sorted;
}
}
The tester class used to test the code has this:
import java.util.ArrayList;
public class ArrayListMethodsTester
{
public static void main(String[] args)
{
//set up
ArrayList<String> animals = new ArrayList<String>();
ArrayListMethods zoo = new ArrayListMethods(animals);
zoo.list.add("ape");
zoo.list.add("dog");
soo.list.add("zebra");
//test isSorted
System.out.println(zoo.isSorted());
System.out.println("Expected: true");
zoo.list.add("cat");
System.out.println(zoo.isSorted());
System.out.println("Expected: false");
zoo.list.remove("cat");
zoo.list.add(0,"cat");
System.out.println(zoo.isSorted());
System.out.println("Expected: false");
}
}
You isSorted method only returns false if the last two elements are not sorted. You should add a break after setting the sorted variable to false:
public boolean isSorted() {
boolean sorted = true;
// TODO: Determine if the array is sorted.
for (int i = 0; i < list.size() - 1; i++){
if (list.get(i).compareTo(list.get(i + 1)) < 0){
sorted = true;
}
else {
sorted = false;
break; // Add break here
}
}
return sorted;
}
Or more simply:
public boolean isSorted() {
for (int i = 0; i < list.size() - 1; i++){
if (list.get(i).compareTo(list.get(i + 1)) > 0){
return false;
}
}
return true;
}
The problem is inside your isSorted() method, you are setting the result as false in the first iteration (because cat is not sorted). But in the second iteration it sets the result as true because "ape" is sorted compared with "dog"
The solution is to finish the process once a false is founded.
So change this:
for (int i = 0; i < list.size() - 1; i++){
if (list.get(i).compareTo(list.get(i + 1)) < 0){
sorted = true;
}
else {
sorted = false;
}
}
For this:
for (int i = 0; i < list.size() - 1; i++){
if (list.get(i).compareTo(list.get(i + 1)) < 0){
sorted = true;
}
else {
return false;
}
}
And it will work fine and it will also improve the performance, since there is no need to check the whole array. If the first couple of elements are not sorted, then the array is not sorted
Related
This question already has answers here:
How to determine if a List is sorted in Java?
(14 answers)
Closed 6 years ago.
Code as follows
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<String>();
arrayList.add("1001");
arrayList.add("999");
String val="";
boolean unsorted=true;
if (val.contains("isAscending")) {
for (int i = 0; i < arrayList.size() - 1; i++) {
if (arrayList.get(i).toLowerCase().compareTo(arrayList.get(i + 1).toLowerCase()) <= 0) {
unsorted = false;
System.out.println(unsorted);
} else {
break;
}
}
} else {
for (int i = 0; i < arrayList.size() - 1; i++) {
if (arrayList.get(i).toLowerCase().compareTo(arrayList.get(i + 1).toLowerCase()) >= 0) {
unsorted = false;
System.out.println(unsorted+" "+"descending");
} else {
break;
}
}
}
}
the above program works correctly but the problem is when I replace
the arraylist with the below arraylist it doesn't work
arrayList.add("22");
arrayList.add("8");
I meant to say that if the first index is followed by a 1 digit number it fails
the same repeats here
arrayList.add("1001");
arrayList.add("1000");
for this the above code works
arrayList.add("1001");
arrayList.add("999");
for this it fails
The requirement is to verify if an arraylist is in sorted order or not no need to sort the arraylist
If you want to find out if your list be sorted, you can use a custom comparator to sort your ArrayList using the actual integers which are represented by the strings. Then, you can compare this sorted list against the original one.
Collections.sort(arrayList, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
try {
// try to compare the two values as integers, if possible
Integer val1 = Integer.valueOf(s1);
Integer val2 = Integer.valueOf(s2);
return val1.compareTo(val2);
}
catch (NumberFormatException e) {
// fall back to sort them as strings
return s1.compareTo(s2);
}
}
});
As #ajb mentioned, it might be simpler to just assume that every string can be converted to an integer, and to deal with the exception elsewhere. In this case we can use:
Collections.sort(arrayList, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return Integer.valueOf(s1).compareTo(Integer.valueOf(s2));
}
});
The method trys to parse the Strings into Integer, if that´s successfull it compares the numbers, if not it compares the Strings.
public class Test {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("1");
arrayList.add("999");
arrayList.add("1001");
boolean isAsc = true;
boolean isSorted = true;
for (int i = 0; i < arrayList.size() -1; i++) {
int a, b;
boolean numbs;
try {
int a = Integer.parseInt(arrayList.get(i));
int b = Integer.parseInt(arrayList.get(i + 1));
if ((isAsc && a > b) || (!isAsc && a < b)) {
isSorted = false;
break;
}
} catch (NumberFormatException) {
if ((isAsc && arrayList.get(i).toLowerCase().compareTo(arrayList.get(i + 1).toLowerCase() > 0) || (arrayList.get(i).toLowerCase().compareTo(arrayList.get(i + 1).toLowerCase() < 0)) {
isSorted = false;
break;
}
}
}
if (isSorted) {
System.out.println("List is sorted !");
} else {
System.out.println("List is not sorted !");
}
}
}
Hope I could help
I need to maintain a sorted data structure from which items can be deleted and added. For that I decided to choose a linked list. Each data item contains a letter and some numbers such as these:
A1480, A1488, B1297, C3119
These need to be maintained in order. I have written code for it which first finds the position into the already sorted linked list where the new item needs to be added and then adds the item to its correct position, therefore maintaining the sorted linked list. It works but some items are misplaced and I am not sure how to fix my code. I do know that there is something wrong with the last loop but i am not sure what it is.
public static void main(String[] args) {
list = new LinkedList<String>();
add("C3138");
add("C3119");
add("A1488");
add("A1480");
add("A1517");
add("B1297");
add("C2597");
add("B1356");
add("C9000");
add("C3517");
add("C3729");
add("C1729");
add("B1729");
}
public static void add(String value) {
// Integer value form the string passed into the method
int valueInt = getInt(value);
// If linked list is empty, add value and return from method
if (list.size() == 0) {
list.add(value);
return;
}
// Compare this item to be added to the first item
int firstNode = getInt(list.get(0));
if (list.get(0).charAt(0) > value.charAt(0)
|| (list.get(0).charAt(0) == value.charAt(0) && firstNode > valueInt)){
list.add(0, value);
return;
}
// Compare this item to the last item
int lastNode = getInt(list.get(list.size() - 1));
if (list.get(list.size() - 1).charAt(0) < value.charAt(0) ||
(list.get(list.size() - 1).charAt(0) == value.charAt(0) && lastNode < valueInt)) {
list.add(list.size(), value);
return;
}
// add the inbetween items
int i = 1;
int tempInt = getInt(list.get(i));
while ((list.get(i).charAt(0) < value.charAt(0)
|| ((list.get(i).charAt(0) == value.charAt(0)) && (valueInt < tempInt)) && i < list.size())) {
tempInt = getInt(list.get(i));
i++;
}
list.add(i, value);
}
public static int getInt(String item) {
return Integer.parseInt(item.replaceAll("\\D", ""));
}
This code below gives me output of:
[A1480, A1517, A1488, B1729, B1297, B1356, C1729, C3729, C3517, C2597,
C3119, C3138, C9000]
and as you can see that some values in between start and finish are misplaced but start and end values are correct. Please help
Try doing this :: Change your last while condition to this::
(list.get(i).charAt(0) < value.charAt(0) || ((list.get(i).charAt(0) == value.charAt(0)) && (valueInt > tempInt)) && i < list.size())
What you are currently doing is that you are incrementing your i unless you hit a value of tempInt which is smaller than varInt, which is why A1517 gets inserted before A1488.
You shall increment your i until the value of tempInt is smaller than `varInt so that you reach the largest position the current element could achieve. I hope I could make it clear.
The working code Ideone link :: http://ideone.com/ZafWEO
Further, it would be better to check the value to i before accessing the linkedlist items. So, the condition shall look like this ::
(i < list.size() && (list.get(i).charAt(0) < value.charAt(0) || ((list.get(i).charAt(0) == value.charAt(0)) && (valueInt > tempInt)))
Take a look at Why is there no SortedList in Java?
If your values are unique, you can just use TreeSet. Generally, if you want a sorted collection, you probably don't want to start with LinkedList.
Why don't you use Comparable?
Scroll to bottom to see the class implemented Comparable
This is answer to your question:
private static LinkedList<SuperRosie> list;
public static void main(String[] args) {
// TODO Auto-generated method stub
list = new LinkedList<SuperRosie>();
add("C3138");
add("C3119");
add("A1488");
add("A1480");
add("A1517");
add("B1297");
add("C2597");
add("B1356");
add("C9000");
add("C3517");
add("C3729");
add("C1729");
add("B1729");
for (int i = 0; i < list.size(); i++)
System.out.println(list.get(i).getValue());
}
private static void add(String value) {
SuperRosie myNewRs = new SuperRosie(value);
int listSize = list.size();
// If linked list is empty, add value and return from method
if (listSize == 0) {
list.add(myNewRs);
return;
}
// Compare this item to be added to the first item
SuperRosie element = list.getFirst();
if (myNewRs.compareTo(element) <= 0) {
list.addFirst(myNewRs);
return;
}else{
if(listSize == 1){
list.addLast(myNewRs);
return;
}
}
// Compare this item to the last item
element = list.getLast();
if (myNewRs.compareTo(element) >= 0) {
list.addLast(myNewRs);
return;
}else{
if(listSize == 1){
list.addFirst(myNewRs);
return;
}
}
// add the inbetween items
int compare = 0;
for (int i = 1; i < listSize; i++) {
element = list.get(i);
compare = myNewRs.compareTo(element);
if (compare <= 0) {
list.add(i, myNewRs);
break;
}
}
}
Example to Sort comparable Linked List:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedList<SuperRosie> list = new LinkedList<SuperRosie>();
list.add(new SuperRosie("C3138"));
list.add(new SuperRosie("C3119"));
list.add(new SuperRosie("A1488"));
list.add(new SuperRosie("A1480"));
list.add(new SuperRosie("A1517"));
list.add(new SuperRosie("B1297"));
list.add(new SuperRosie("C2597"));
list.add(new SuperRosie("B1356"));
list.add(new SuperRosie("C9000"));
list.add(new SuperRosie("C3517"));
list.add(new SuperRosie("C3729"));
list.add(new SuperRosie("C1729"));
list.add(new SuperRosie("B1729"));
Collections.sort(list);
for(SuperRosie rs : list)
System.out.println(rs.getValue());
}
}
And SuperRosie.java class implements from Comparable
public class SuperRosie implements Comparable<SuperRosie> {
private String value;
public SuperRosie(String value) {
this.value = value;
}
public String getValue() {
return value;
}
#Override
public int compareTo(SuperRosie arg0) {
int compareFirst = this.value.charAt(0) - arg0.value.charAt(0);
return compareFirst == 0 ? (Integer.parseInt(this.value.replaceAll(
"\\D", "")) - Integer
.parseInt(arg0.value.replaceAll("\\D", ""))) : compareFirst;
}
public static Comparator<SuperRosie> FruitNameComparator = new Comparator<SuperRosie>() {
public int compare(SuperRosie rosie1, SuperRosie rosie2) {
String rosieValue1 = rosie1.value.toUpperCase();
String rosieValue2 = rosie2.value.toUpperCase();
// ascending order
return rosieValue1.compareTo(rosieValue2);
// descending order
//return rosieValue2.compareTo(rosieValue1);
}
};
}
According to the performance problems, I suggest another performance solution.
private static LinkedList<String> list;
public static void main(String[] args) {
list = new LinkedList<>();
add("C3138");
add("C3119");
add("A1488");
add("A1480");
add("A1517");
add("B1297");
add("C2597");
add("B1356");
add("C9000");
add("C3517");
add("C3729");
add("C1729");
add("B1729");
for (int i = 0; i < list.size(); i++)
System.out.println(list.get(i));
}
private static void add(String value){
// don't check empty array, check to add in the first, last element.
// Each case, it works but when array has more than 1 element,
// so the above check are useless, run will cost memory, steps,....
// So don't, please do just the following
int insertIndex = 0;
for(String element : list){
if(compare(value, element) <= 0){ // or whatever compare way you want
break;
}else{
insertIndex+=1;
}
}
list.add(insertIndex, value);
}
private static int compare(String value1, String value2){
int compareFirst = value1.charAt(0) - value2.charAt(0);
return compareFirst == 0 ? (Integer.parseInt(value1.replaceAll(
"\\D", "")) - Integer
.parseInt(value2.replaceAll("\\D", ""))) : compareFirst;
}
public static ArrayList<ArrayList<HSSFCell>> newTogether(ArrayList<ArrayList<HSSFCell>> sheetData) {
ArrayList<ArrayList<HSSFCell>> temporary = new ArrayList<ArrayList<HSSFCell>>();
for(int i = 0; i < sheetData.size(); i++) {
ArrayList<HSSFCell> list = sheetData.get(i);
if (list.get(3).getCellType() == Cell.CELL_TYPE_NUMERIC) {
if(Integer.parseInt(list.get(3).getStringCellValue()) > 100) {
temporary.add(list);
sheetData.remove(i);
i--;
}
}
}
for(int i = 0; i < sheetData.size(); i++) {
ArrayList<HSSFCell> list = sheetData.get(i);
temporary.add(list);
}
return temporary;
}
What I am trying to do with my code is have the 2D ArrayList take out any numbers greater than 100 and put them in the beginning of the ArrayList, while preserving the order of the remaining elements. However, this code just returns an ArrayList in the original order, and if I add a println to either if, I get nothing. Could someone point out what it is I'm doing wrong?
Have you tried putting a println in front of the first if to check what getStringCellValue() returns?
btw. since Collections.sort is guaranteed to be stable according to the API documentation, you could use that. Should be faster than your way of doing it.
That could look like this
private static boolean biggerThan100(ArrayList<HSSFCell> list) {
return list.get(3).getCellType() == Cell.CELL_TYPE_NUMERIC &&
(Integer.parseInt(list.get(3).getStringCellValue()) > 100);
}
public static ArrayList<ArrayList<HSSFCell>> newTogether(ArrayList<ArrayList<HSSFCell>> sheetData) {
ArrayList<ArrayList<HSSFCell>> temp = new ArrayList<>(sheetData);
Collections.sort(temp, new Comparator<ArrayList<HSSFCell>>() {
public int compare(ArrayList<HSSFCell> a, ArrayList<HSSFCell> b) {
if(biggerThan100(a) && !biggerThan100(b)) return -1;
else if(biggerThan100(b) && !biggerThan100(a)) return 1;
else return 0;
}
});
return temp;
}
(Full disclosure: this is for some homework I can't seem to figure out.)
The task: Identify duplicates in a list and add them to another ArrayList to be printed out.
Specifications: I am NOT allowed to use any collection other than an ArrayList, so I can't use something like a Set. It seems like every answer on StackOverflow recommends use of a Set, which is why I decided to ask this question.
What I've attempted so far:
public static void deleteDuplicates(List<String> list)
{
int pointer = 1;
List<String> duplicates = new ArrayList<String>();
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i).equals(list.get(pointer))) {
duplicates.add(list.get(i));
if (pointer == 1) {
duplicates.add(list.get(pointer));
} else if ((pointer + 1) == list.size() - 1) {
duplicates.add(list.get(pointer));
}
pointer++;
} else {
display(duplicates);
duplicates = new ArrayList<String>();
pointer++;
}
}
}
The test data:
List<String> duplicated = new ArrayList<String>();
duplicated.add("3");
duplicated.add("3");
duplicated.add("30");
duplicated.add("46");
duplicated.add("46");
What's not working: When the size of the list is an odd number, the duplicates report correctly. When the size of the list is an even number, only the first two duplicates are reported.
The problem with your approach was the loop exits before it do the if-else check for last element. On the last iteration the if condition satisfies and it adds to duplicates but it wont enter the for loop again to goto the else part. So it does'nt get dispalyed. Try
public static void deleteDuplicates(List<String> list)
{
int pointer = 1;
List<String> duplicates = new ArrayList<String>();
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i).equals(list.get(pointer))) {
duplicates.add(list.get(i));
if (pointer == 1) {
duplicates.add(list.get(pointer));
} else if ((pointer + 1) == list.size() - 1) {
duplicates.add(list.get(pointer));
}
pointer++;
} else if(duplicates.size() > 0) {
display(duplicates);
duplicates.clear();
pointer++;
}
}
if(duplicates.size() > 0){
display(duplicates);
}
}
Although Syam S answer is right but this will work for unsorted array too:
public static void deleteDuplicates(List<String> list)
{
List<String> duplicates = new ArrayList<String>();
for (int j = 0; j < list.size() - 2; j++) {
int pointer = j;
for (int i = j+1; i < list.size() - 1; i++) {
if (list.get(i).equals(list.get(j))) {
duplicates.add(list.get(i));
duplicates.add(list.get(j));
}
if(duplicates.size() > 0){
System.out.println(duplicates);
duplicates.clear();
}
}
}
}
you can see the working version in Ideone
Try this:
Extending the ArrayList
1)
boolean result = false;
if(!contains(object))
result= super.add(object);
return result;
OR
2)
ArrayList<String> myList = new ArrayList<String>()
{
#Override
public boolean add(String object)
{
boolean present = false;
boolean result = false;
for(int i=0;i<size();i++)
{
if(object.equals(get(i)))
{
present = true;
break;
}
}
if(!present)
result= super.add(object);
return result;
}
};
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("1");
myList.add("1");
System.out.println(myList);
I am writing code to check if my array is in ascending or descending order. If the boolean 'ascending' is true, then I check if it is ascending. If it is false, then I check for descending. I need help checking whether the array is descending or not... I have the code to check ascending which is written below:
protected boolean isSorted(boolean ascending) {
boolean result = false;
if (ascending) {
for (int i=0;i<data.length-1;i++) {
if(data[i] < data[i+1]) {
result = true;
} else if(data[i] > data[i+1]) {
result = false;
}
}
} else {
//code to check for descending order
}
}
The first part of the if (the "ascending" check) is wrong, it should be:
for (int i = 0; i < data.length-1; i++) {
if (data[i] > data[i+1]) {
return false;
}
}
return true;
Conversely, the descending check should be (and notice that it's enough to change the direction of the comparison operator):
for (int i = 0; i < data.length-1; i++) {
if (data[i] < data[i+1]) {
return false;
}
}
return true;
In both cases, you have to break out of the loop as soon as you find a single pair of numbers that do not hold the ascending-or-descending property, and only return true after the loop exits.
You can cheat and do it in one loop if you like and remove one addition:
protected boolean isSorted(boolean ascending) {
for (int i = 1; i < data.length; i++) {
if (data[i-1] == data[i]) {
continue;
}
if ((data[i-1] > data[i]) == ascending) {
return false;
}
}
return true;
}
NOTE: I am building on the code by #OscarLopez so upvote his if you upvote mine.
To check if ArrayList<Integer> is in descending order try this:
boolean isSorted(ArrayList<Integer> list){
boolean sorted = true;
for (int i = 1; i < list.size(); i++) {
if (list.get(i-1) >= (list.get(i)) ) {
sorted = true;
} else {
return false;
} // if else ends
} // for "i" ends
return sorted;
}