Tutorial JavaYa
Tutorial JavaYa
Java Ya
Listado completo de tutoriales
1 Instalación de Java
Descarga
Para poder hacer este curso debemos instalar el compilador de Java y la máquina
virtual de Java. Estas herramientas las podemos descargar de:
Java SE Development Kit (descargar el Windows x64 o si tiene un sistema operativo de
32 bits instale el Windows x86).
Una vez que tenemos el JDK (Java Development Kit) procedemos a instalarlo:
La versión a instalar conviene que sea la última (en este momento disponemos la
versión 8)
Una vez finalizado el proceso de instalación debe aparecer un diálogo similar a este y
presionamos el botón Close (por el momento no vamos a instalar "Tutorials, Api
documentation etc.):
Retornar
Listado completo de tutoriales
2 Instalación del editor Eclipse
En el concepto anterior procedimos a instalar el lenguaje Java (con dichas herramientas podemos ejecutar y
compilar programas codificados en java), pero ahora necesitamos instalar el Eclipse que es un editor para
codificar los programas (si bien podemos utilizar otros editores, nosotros utilizaremos este para seguir el curso)
Descarga
Para la descarga del editor Eclipse lo hacemos del sitio:
Eclipse
Una vez que descargamos el instalador de Eclipse procedemos a ejecutarlo y debemos elegir el entorno
"Eclipse IDE for Java Developers":
Seleccionamos la carpeta donde se instalará el Eclipse:
Una vez instalado en forma completo el "Eclipse IDE for Java Developers" nos dirigimos a la carpeta donde se
instalaron los archivos y procedemos a ejecutar el programa eclipse.exe (podemos ingresar desde el acceso
directo que se crea en el escritorio)
Luego la primera vez que ejecutemos el editor Eclipse aparece un diálogo para seleccionar la carpeta donde
se almacenarán los programas que desarrollaremos (podemos crear una carpeta donde almacenaremos todos
los proyectos que desarrollaremos en el curso, si indicamos una carpeta que no existe el mismo Eclipse la
crea):
Luego de configurar la carpeta donde se crearán los proyecto aparece el editor con una pantalla de
presentación (Welcome):
Esta ventana de bienvenida la podemos cerrar seleccionando el ícono: "Workbench", con lo que aparece el
entorno de trabajo del Eclipse (si queremos nuevamente ver la ventana de bienvenida podemos activarla
desde el menú de opciones: Help > Welcome)
El entorno de trabajo del Eclipse es:
Retornar
Listado completo de tutoriales
3 Pasos para crear un programa con
Eclipse
El Eclipse es un entorno de trabajo profesional, por lo que en un principio puede parecer complejo
el desarrollo de nuestros primeros programas.
Todo programa en Eclipse requiere la creación de un "Proyecto", para esto debemos seleccionar
desde el menú de opciones:
Ahora aparece el diálogo donde debemos definir el nombre de nuestro proyecto:
En el campo de texto "Project Name" ingresamos como nombre: Proyecto1 y dejamos todas las
otras opciones del diálogo con los valores por defecto. Presionamos el botón "Finish".
Ahora en la ventana de "Package Explorer" aparece el proyecto que acabamos de crear:
Como segundo paso veremos que todo programa en Java requiere como mínimo una clase. Para
crear una clase debemos seleccionar desde el menú de opciones:
O desde la barra de íconos del Eclipse:
En el diálogo que aparece debemos definir el nombre de la clase (en nuestro primer ejemplo la
llamaremos Clase1 (con mayúscula la letra C), luego veremos que es importante definir un
nombre que represente al objetivo de la misma), los otros datos del diálogo los dejamos con los
valores por defecto:
Luego de presionar el botón "Finish" tenemos el archivo donde podemos codificar nuestro primer
programa:
Más adelante veremos los archivos que se crean en un proyecto, ahora nos dedicaremos a
codificar nuestro primer programa. En la ventana de edición ya tenemos el esqueleto de una clase
de Java que el entorno Eclipse nos creó automáticamente.
Todo programa en Java debe definir la función main. Esta función la debemos codificar dentro de
la clase: "Clase1".
}
Es decir tenemos codificado en el entorno del Eclipse nuestro primer programa:
Como último paso debemos compilar y ejecutar el programa, esto lo podemos hacer desde el
menú de opciones:
O desde la barra de íconos del Eclipse:
Si no hay errores de codificación debemos ver el resultado de la ejecución en una ventana del
Eclipse llamada "Console" que aparece en la parte inferior (puede aparecer un diálogo pidiendo
que grabemos el archivo, el cual confirmamos):
Lo más importante es que quede claro los pasos que debemos dar para crear un proyecto en
Java. El objetivo de una clase, la función main etc. los veremos a lo largo de este curso.
Retornar
Listado completo de tutoriales
4 Objetivos del curso y nociones básicas
indispensables
El curso está ideado para ser desarrollado por una persona que no conoce nada de programación y se utilice
Java como primer lenguaje.
El objetivo fundamental de este tutorial es permitir que el estudiante pueda resolver problemas de distinta índole
(matemáticos, administrativos, gráficos, contables etc.) empleando como herramienta la computadora.
Hay que tener en cuenta que para llegar a ser programador se debe recorrer un largo camino donde cada tema
es fundamental para conceptos futuros. Es importante no dejar temas sin entender y relacionar.
La programación a diferencia de otras materias como podría ser la historia requiere un estudio metódico y
ordenado (en historia se puede estudiar la edad media sin tener grandes conocimientos de la edad antigua)
La programación es una actividad nueva para el estudiante, no hay en los estudios primarios y secundarios una
materia parecida.
Es bueno tenerse paciencia cuando los problemas no se resuelven por completo, pero es de fundamental
importancia dedicar tiempo al análisis individual de los problemas.
Qué es un programa?
Programa: Conjunto de instrucciones que entiende un ordenador para realizar una actividad.
Todo programa tiene un objetivo bien definido: un procesador de texto es un programa que permite cargar,
modificar e imprimir textos, un programa de ajedrez permite jugar al ajedrez contra el ordenador u otro
contrincante humano.
La actividad fundamental del programador es resolver problemas empleando el ordenador como herramienta
fundamental.
Diagrama de flujo
Estos son los elementos esenciales que intervienen en el desarrollo de un diagrama de flujo.
Podemos identificar:
Datos conocidos:
Horas trabajadas en el mes.
Pago por hora.
Proceso:
Cálculo del sueldo multiplicando la cantidad de horas por el pago por hora.
Información resultante:
Sueldo mensual.
Esta forma de expresar un problema identificando sus datos conocidos, procesos e información resultante
puede llegar a ser engorrosa para problemas complejos donde hay muchos datos conocidos y procesos. Es por
eso que resulta mucho más efectivo representar los pasos para la resolución del problema mediante un
diagrama de flujo.
El diagrama de flujo nos da una idea del orden de ejecución de las actividades en el tiempo. Primero cargamos
los datos de entrada, luego hacemos las operaciones necesarias y por último mostramos los resultados.
Lenguaje de computación: Conjunto de instrucciones que son interpretadas por una computadora para realizar
operaciones, mostrar datos por pantalla, sacar listados por impresora, entrar datos por teclado, etc.
Para el ejemplo planteado la variable horasTrabajadas almacena la cantidad de horas trabajadas por el
operario. La variable valorHora almacena el precio de una hora de trabajo. La variable sueldo almacena el
sueldo a abonar al operario.
En el ejemplo tenemos tres variables.
Tipos de variable:
Una variable puede almacenar:
Valores Enteros (100, 260, etc.)
Valores Reales (1.24, 2.90, 5.00, etc.)
Cadenas de caracteres ("Juan", "Compras", "Listado", etc.)
Hay que tener en cuenta que el entorno de programación "Eclipse" no a sido desarrollado pensando en un
principiante de la programación. Lo mismo ocurre con el propio lenguaje Java, es decir su origen no tiene como
principio el aprendizaje de la programación. Debido a estos dos puntos veremos que a medida que avanzamos
con el tutorial muchos conceptos que iremos dejando pendientes se irán aclarando.
Codificaremos el problema propuesto para repasar los pasos para la creación de un proyecto en Eclipse,
creación de la clase principal, definición de la función main y el posterior desarrollo del algoritmo del problema.
Pasos.
1 Creación del proyecto (tema visto anteriormente). Podemos asignarle como nombre: SueldoOperario
(normalmente uno busca un nombre representativo al programa que desarrolla)
2 Creación de la clase. Definiremos como nombre el mismo que le asignamos al proyecto (esto no es
obligatorio como veremos más adelante un proyecto puede contener varias clases)
Es decir disponemos como nombre de la clase: SueldoOperario.
Inicializamos el campo que solicita el "Name" con "SueldoOperario".
import java.util.Scanner;
5 Si no hay errores sintácticos procedemos a activar la ventana de la "Console" con el mouse y cargamos por
teclado los dos datos que se solicitan (la cantidad de horas trabajadas y el precio de la hora):
Estos cinco pasos fundamentales debemos llevar a cabo cada vez que desarrollemos un nuevo programa en
Java.
Explicación.
Ahora veremos una explicación de varias partes de nuestro programa y otras partes quedarán pendientes para
más adelante ya que en este momento difícilmente se entiendan.
1. Concepto de una clase. Veremos más adelante que en Java todo debe estar contenido en clases, por lo
que hasta el problema más elemental debe estar contenido en una clase. Para declarar una clase
utilizamos la sintaxis:
El nombre de la clase no puede tener espacios en blanco, comienza con una letra mayúscula y en caso de
estar constituida por dos o más palabras el primer caracter va en mayúsculas, no puede empezar con un
número, pero si puede llevar números a partir del segundo caracter. Toda clase debe tener una llave de
apertura y una llave de cierre.
2. Todo programa constituido por una única clase debe tener definida la función main:
La función main es la primera que se ejecuta y debe llevar la sintaxis indicada anteriormente (más adelante
veremos que significa el parámetro ar, las palabras claves public, static y void. La función main tiene una
llave de apertura y una llave de cierre (similar a la clase). La función main debe estar contenida en la clase.
3. Cuando se requieren utilizar otras clases debemos importarlas previo a la declaración de la clase (en
nuestro problema utilizamos la clase Scanner que se encuentra en el paquete java.util por lo que la
importamos con la siguiente sintaxis:
import java.util.Scanner;
En la main creamos un objeto de la clase Scanner que nos permitirá ingresar por teclado los valores:
1. Por el momento haremos todo el algoritmo dentro de la función main. Es decir el resto siempre será lo
mismo (declarar un proyecto, declarar una clase, definir una función main)
2. Si observamos el diagrama de flujos vemos que debemos definir tres variables: (horasTrabajadas,
costoHora,sueldo), aquí es donde debemos definir que tipos de datos se almacenarán en las mismas.
La cantidad de horas normalmente será un valor entero (ej. 100 150 230 etc.), pero el costo de la
hora es muy común que sea un valor real (ej. 5,35 7,50 etc.) y como el sueldo resulta de multiplicar las
horas trabajadas por el costo por hora el mismo deberá ser real.
int horasTrabajadas;
float costoHora;
float sueldo;
Utilizamos la palabra clave int para definir variables enteras (en Java las palabras claves deben ir
obligatoriamente en minúsculas, sino se produce un error sintáctico) Luego de la palabra clave debemos
indicar el nombre de la variable, por ejemplo: horasTrabajadas (se propone que el nombre de la variable
comience con minúsculas y en caso de estar constituida por dos palabras o más a partir de la segunda
palabra el primer caracter se especifique con mayúsculas (un nombre de variable no puede tener espacios
en blanco, empezar con un número, ni tampoco utilizar caracteres especiales)
Debemos buscar siempre nombres de variables que nos indiquen que almacenan (no es conveniente llamar
a nombres de variables con letras individuales)
System.out.print(sueldo);
4. Para hacer la entrada de datos por teclado en Java se complica. Utilizaremos una clase llamada
Scanner que nos facilita el ingreso de datos. Por eso tuvimos que importar la clase Scanner que se
encuentra en el paquete java.util en la primer línea de nuestro programa.
En la función main debemos crear un objeto de la clase Scanner con la siguiente sintaxis:
Luego para cargar valores enteros por teclado debemos implementar la siguiente sintaxis:
horasTrabajadas=teclado.nextInt();
Pero si el dato a cargar se trata de un valor float luego debemos utilizar la siguiente sintaxis:
costoHora=teclado.nextFloat();
5. Las operaciones que indicamos en el diagrama de flujo mediante la figura rectángulo la codificamos tal
cual:
sueldo=horasTrabajadas * costoHora;
Podemos ver una relación entre las instrucciones que debemos utilizar para cada símbolo del diagrama de flujo:
int horasTrabajadas;
float costoHora;
float sueldo;
No representamos con símbolos los mensajes a mostrar previo a la carga de datos por teclado:
Como hemos visto hasta ahora hay muchas partes de nuestro código que no entendemos pero son
indispensables para la implementación de nuestros programas, a medida que avancemos con el curso muchos
de estos conceptos se irán aclarando.
Retornar
Listado completo de tutoriales
5 Errores sintácticos y lógicos
Confeccionaremos un problema y agregaremos adrede una serie de errores tipográficos. Este tipo
de errores siempre son detectados por el COMPILADOR, antes de ejecutar el programa.
A los errores tipográficos, como por ejemplo la falta de puntos y comas, nombres de variables
incorrectas, falta de paréntesis, palabras claves mal escritas, etc. los llamamos errores
SINTACTICOS.
Un programa no se puede ejecutar sin corregir absolutamente todos los errores sintácticos.
Existe otro tipo de errores llamados ERRORES LOGICOS. Este tipo de errores en programas
grandes (miles de líneas) son más difíciles de localizar. Por ejemplo un programa que permite
hacer la facturación pero la salida de datos por impresora es incorrecta.
Problema:
Diagrama de flujo:
Proyecto:
Como podemos observar aparece subrayado la línea donde disponemos System con minúsculas
como en la línea que imprimimos la variable superficie con mayúsculas. Si modificamos y
corregimos los dos errores sintácticos podremos ejecutar nuestro programa.
import java.util.Scanner;
import java.util.Scanner;
Como podemos observar si ejecutamos el programa no presenta ningún error de compilación. Pero
luego de ingresar el valor del lado del cuadrado (por ejemplo el valor 10) obtenemos como resultado
un valor incorrecto (imprime el 1000), esto debido que definimos incorrectamente la fórmula para
calcular la superficie del cuadrado:
Retornar
Listado completo de tutoriales
6 Estructura de programación
secuencial
Problema:
Diagrama de flujo:
Tenemos dos entradas num1 y num2 (recordar cuáles son los nombres de variables
correctas), dos operaciones: realización de la suma y del producto de los valores
ingresados y dos salidas, que son los resultados de la suma y el producto de los
valores ingresados. En el símbolo de impresión podemos indicar una o más salidas,
eso queda a criterio del programador, lo mismo para indicar las entradas por teclado.
Programa:
import java.util.Scanner;
Recordemos que tenemos que seguir todos los pasos vistos para la creación de un
proyecto, su clase, definición de la función main y la codificación del diagrama de flujo.
int num1,num2,suma,producto;
System.out.println(suma);
Problemas propuestos
1. Realizar la carga del lado de un cuadrado, mostrar por pantalla el perímetro del
mismo (El perímetro de un cuadrado se calcula multiplicando el valor del lado por
cuatro)
Solución
Retornar
Listado completo de tutoriales
7 Estructuras condicionales
simples y compuestas
Ingresar el sueldo de una persona, si supera los 3000 pesos mostrar un mensaje en
pantalla indicando que debe abonar impuestos.
Diagrama de flujo:
Podemos observar lo siguiente: Siempre se hace la carga del sueldo, pero si el sueldo
que ingresamos supera 3000 pesos se mostrará por pantalla el mensaje "Esta persona
debe abonar impuestos", en caso que la persona cobre 3000 o menos no aparece
nada por pantalla.
Programa:
import java.util.Scanner;
La palabra clave "if" indica que estamos en presencia de una estructura condicional;
seguidamente disponemos la condición entre paréntesis. Por último encerrada entre
llaves las instrucciones de la rama del verdadero.
Es necesario que las instrucciones a ejecutar en caso que la condición sea verdadera estén
encerradas entre llaves { }, con ellas marcamos el comienzo y el fin del bloque del
verdadero.
Representación gráfica:
En una estructura condicional compuesta tenemos entradas, salidas, operaciones,
tanto por la rama del verdadero como por la rama del falso.
Problema:
Realizar un programa que solicite ingresar dos números distintos y muestre por
pantalla el mayor de ellos.
Diagrama de flujo:
Se hace la entrada de num1 y num2 por teclado. Para saber cual variable tiene un
valor mayor preguntamos si el contenido de num1 es mayor (>) que el contenido de
num2, si la respuesta es verdadera vamos por la rama de la derecha e imprimimos
num1, en caso que la condición sea falsa vamos por la rama de la izquierda (Falsa) e
imprimimos num2.
Como podemos observar nunca se imprimen num1 y num2 simultáneamente.
Programa:
import java.util.Scanner;
System.out.print(num1);
} else {
System.out.print(num2);
}
}
}
>Operadores Relacionales:
> (mayor)
< (menor)
>= (mayor o igual)
<= (menor o igual)
== (igual)
!= (distinto)
Operadores Matemáticos
+ (más)
- (menos)
* (producto)
/ (división)
% (resto de una división) Ej.: x=13%5; {se guarda 3}
Hay que tener en cuenta que al disponer una condición debemos seleccionar que
operador relacional se adapta a la pregunta.
Ejemplos:
Los problemas que se pueden presentar son infinitos y la correcta elección del
operador sólo se alcanza con la práctica intensiva en la resolución de problemas.
Problemas propuestos
1. Realizar un programa que lea por teclado dos números, si el primero es mayor al
segundo informar su suma y diferencia, en caso contrario informar el producto y la
división del primero respecto al segundo.
3. Se ingresa por teclado un número positivo de uno o dos dígitos (1..99) mostrar un
mensaje indicando si el número tiene uno o dos dígitos.
(Tener en cuenta que condición debe cumplirse para tener dos dígitos, un número
entero)
Solución
Retornar
Listado completo de tutoriales
8 Estructuras condicionales
anidadas
Decimos que una estructura condicional es anidada cuando por la rama del verdadero
o el falso de una estructura condicional hay otra estructura condicional.
Problema:
Confeccionar un programa que pida por teclado tres notas de un alumno, calcule el
promedio e imprima alguno de estos mensajes:
Si el promedio es >=7 mostrar "Promocionado".
Si el promedio es >=4 y <7 mostrar "Regular".
Si el promedio es <4 mostrar "Reprobado".
Diagrama de flujo:
Analicemos el siguiente diagrama. Se ingresan tres valores por teclado que
representan las notas de un alumno, se obtiene el promedio sumando los tres valores y
dividiendo por 3 dicho resultado (Tener en cuenta que si el resultado es un valor real
solo se almacena la parte entera).
Primeramente preguntamos si el promedio es superior o igual a 7, en caso afirmativo
va por la rama del verdadero de la estructura condicional mostramos un mensaje que
indica "Promocionado" (con comillas indicamos un texto que debe imprimirse en
pantalla).
En caso que la condición nos de falso, por la rama del falso aparece otra estructura
condicional, porque todavía debemos averiguar si el promedio del alumno es superior o
igual a cuatro o inferior a cuatro.
Estamos en presencia de dos estructuras condicionales compuestas.
Programa:
import java.util.Scanner;
int nota1,nota2,nota3;
2. Se ingresa por teclado un valor entero, mostrar una leyenda que indique si el
número es positivo, nulo o negativo.
Solución
Retornar
9 Condiciones compuestas con Listado completo de tutoriales
operadores lógicos
Operador &&
Problema:
Confeccionar un programa que lea por teclado tres números distintos y nos muestre el
mayor.
Diagrama de flujo:
Este ejercicio está resuelto sin emplear operadores lógicos en un concepto anterior del
tutorial. La primera estructura condicional es una ESTRUCTURA CONDICIONAL
COMPUESTA con una CONDICION COMPUESTA.
Podemos leerla de la siguiente forma:
Si el contenido de la variable num1 es mayor al contenido de la variable num2 Y si el
contenido de la variable num1 es mayor al contenido de la variable num3 entonces la
CONDICION COMPUESTA resulta Verdadera.
Si una de las condiciones simples da falso la CONDICION COMPUESTA da Falso y
continua por la rama del falso.
Es decir que se mostrará el contenido de num1 si y sólo si num1>num2 y num1>num3.
En caso de ser Falsa la condición, analizamos el contenido de num2 y num3 para ver
cual tiene un valor mayor.
En esta segunda estructura condicional no se requieren operadores lógicos al haber
una condición simple.
Programa:
import java.util.Scanner;
Operador ||
Traducido se lo lee como ?O?. Si la condición 1 es Verdadera O la condición 2 es
Verdadera, luego ejecutar la rama del Verdadero.
Cuando vinculamos dos o más condiciones con el operador ?Or", con que una de las
dos condiciones sea Verdadera alcanza para que el resultado de la condición
compuesta sea Verdadero.
Problema:
Se carga una fecha (día, mes y año) por teclado. Mostrar un mensaje si corresponde al
primer trimestre del año (enero, febrero o marzo) Cargar por teclado el valor numérico
del día, mes y año.
Ejemplo: dia:10 mes:1 año:2010.
Diagrama de flujo:
La carga de una fecha se hace por partes, ingresamos las variables dia, mes y año.
Mostramos el mensaje "Corresponde al primer trimestre" en caso que el mes ingresado
por teclado sea igual a 1, 2 ó 3.
En la condición no participan las variables dia y año.
Programa:
import java.util.Scanner;
Problemas propuestos
1. Realizar un programa que pida cargar una fecha cualquiera, luego verificar si dicha
fecha corresponde a Navidad.
2. Se ingresan tres valores por teclado, si todos son iguales se imprime la suma del
primero con el segundo y a este resultado se lo multiplica por el tercero.
3. Se ingresan por teclado tres números, si todos los valores ingresados son menores
a 10, imprimir en pantalla la leyenda "Todos los números son menores a diez".
4. Se ingresan por teclado tres números, si al menos uno de los valores ingresados
es menor a 10, imprimir en pantalla la leyenda "Alguno de los números es menor a
diez".
7. Escribir un programa en el cual: dada una lista de tres valores numéricos distintos
se calcule e informe su rango de variación (debe mostrar el mayor y el menor de
ellos)
Solución
Retornar
Listado completo de tutoriales
10 Estructura repetitiva while
Problema 1:
Sin conocer las estructuras repetitivas podemos resolver el problema empleando una
estructura secuencial. Inicializamos una variable con el valor 1, luego imprimimos la
variable, incrementamos nuevamente la variable y así sucesivamente.
Diagrama de flujo:
La operación x=x + 1 se lee como "en la variable x se guarda el contenido de x más 1".
Es decir, si x contiene 1 luego de ejecutarse esta operación se almacenará en x un 2.
No existe una RECETA para definir una condición de una estructura repetitiva, sino que
se logra con una práctica continua solucionando problemas.
Una vez planteado el diagrama debemos verificar si el mismo es una solución válida al
problema (en este caso se debe imprimir los números del 1 al 100 en pantalla), para
ello podemos hacer un seguimiento del flujo del diagrama y los valores que toman las
variables a lo largo de la ejecución:
x
1
2
3
4
.
.
100
101 Cuando x vale 101 la condición de la estructura repeti
en este caso finaliza el diagrama.
Programa:
Respuestas:
Problema 2:
Escribir un programa que solicite la carga de un valor positivo y nos muestre desde 1
hasta el valor ingresado de uno en uno.
Ejemplo: Si ingresamos 30 se debe mostrar en pantalla los números del 1 al 30.
Diagrama de flujo:
Podemos observar que se ingresa por teclado la variable n. El operador puede cargar
cualquier valor.
Si el operador carga 10 el bloque repetitivo se ejecutará 10 veces, ya que la condición
es ?Mientras x<=n ?, es decir ?mientras x sea menor o igual a 10?; pues x comienza
en uno y se incrementa en uno cada vez que se ejecuta el bloque repetitivo.
A la prueba del diagrama la podemos realizar dándole valores a las variables; por
ejemplo, si ingresamos 5 el seguimiento es el siguiente:
n x
5 1 (Se imprime el contenido de x)
2 " "
3 " "
4 " "
5 " "
6 (Sale del while porque 6 no es menor o igual a 5)
Programa:
import java.util.Scanner;
Los nombres de las variables n y x pueden ser palabras o letras (como en este caso)
Problema 3:
Desarrollar un programa que permita la carga de 10 valores por teclado y nos muestre
posteriormente la suma de los valores ingresados y su promedio.
Diagrama de flujo:
En este problema, a semejanza de los anteriores, llevamos un CONTADOR llamado x
que nos sirve para contar las vueltas que debe repetir el while.
También aparece el concepto de ACUMULADOR (un acumulador es un tipo especial
de variable que se incrementa o decrementa con valores variables durante la ejecución
del programa)
Hemos dado el nombre de suma a nuestro acumulador. Cada ciclo que se repita la
estructura repetitiva, la variable suma se incrementa con el contenido ingresado en la
variable valor.
Este es un seguimiento del diagrama planteado. Los números que toma la variable
valor dependerá de qué cifras cargue el operador durante la ejecución del programa.
El promedio se calcula al salir de la estructura repetitiva (es decir primero sumamos los
10 valores ingresados y luego los dividimos por 10)
Hay que tener en cuenta que cuando en la variable valor se carga el primer valor (en
este ejemplo 5) al cargarse el segundo valor (16) el valor anterior 5 se pierde, por ello
la necesidad de ir almacenando en la variable suma los valores ingresados.
Programa:
import java.util.Scanner;
Problema 4:
Diagrama de flujo:
Podemos observar que dentro de una estructura repetitiva puede haber estructuras
condicionales (inclusive puede haber otras estructuras repetitivas que veremos más
adelante)
Programa:
import java.util.Scanner;
Problemas propuestos
Ha llegado la parte fundamental, que es el momento donde uno desarrolla
individualmente un algoritmo para la resolución de problemas.
El tiempo a dedicar a esta sección EJERCICIOS PROPUESTOS debe ser mucho
mayor que el empleado a la sección de EJERCICIOS RESUELTOS.
La experiencia dice que debemos dedicar el 80% del tiempo a la resolución individual
de problemas y el otro 20% al análisis y codificación de problemas ya resueltos por
otras personas.
Es de vital importancia para llegar a ser un buen PROGRAMADOR poder resolver
problemas en forma individual.
3. En una empresa trabajan n empleados cuyos sueldos oscilan entre $100 y $500,
realizar un programa que lea los sueldos que cobra cada empleado e informe
cuántos empleados cobran entre $100 y $300 y cuántos cobran más de $300.
Además el programa deberá informar el importe que gasta la empresa en sueldos
al personal.
5. Mostrar los múltiplos de 8 hasta el valor 500. Debe aparecer en pantalla 8 16 24,
etc.
6. Realizar un programa que permita cargar dos listas de 15 valores cada una.
Informar con un mensaje cual de las dos listas tiene un valor acumulado mayor
(mensajes "Lista 1 mayor", "Lista 2 mayor", "Listas iguales")
Tener en cuenta que puede haber dos o más estructuras repetitivas en un
algoritmo.
Solución
Retornar
Listado completo de tutoriales
11 Estructura repetitiva for
Representación gráfica:
En su forma más típica y básica, esta estructura requiere una variable entera que
cumple la función de un CONTADOR de vueltas. En la sección indicada como
"inicialización contador", se suele colocar el nombre de la variable que hará de
contador, asignándole a dicha variable un valor inicial. En la sección de "condición" se
coloca la condición que deberá ser verdadera para que el ciclo continúe (en caso de un
falso, el ciclo se detendrá). Y finalmente, en la sección de "incremento contador" se
coloca una instrucción que permite modificar el valor de la variable que hace de
contador (para permitir que alguna vez la condición sea falsa)
Cuando el ciclo comienza, antes de dar la primera vuelta, la variable del for toma el
valor indicado en la sección de de "inicialización contador". Inmediatamente se verifica,
en forma automática, si la condición es verdadera. En caso de serlo se ejecuta el
bloque de operaciones del ciclo, y al finalizar el mismo se ejecuta la instrucción que se
haya colocado en la tercer sección.
Seguidamente, se vuelve a controlar el valor de la condición, y así prosigue hasta que
dicha condición entregue un falso.
La variable del for puede tener cualquier nombre. En este ejemplo se la ha definido con
el nombre f.
Analicemos el ejemplo:
La variable f PUEDE ser modificada dentro del bloque de operaciones del for, aunque
esto podría causar problemas de lógica si el programador es inexperto.
La variable f puede ser inicializada en cualquier valor y finalizar en cualquier valor.
Además, no es obligatorio que la instrucción de modificación sea un incremento del tipo
contador (f++).
Cualquier instrucción que modifique el valor de la variable es válida. Si por ejemplo se
escribe f=f+2 en lugar de f++, el valor de f será incrementado de a 2 en cada vuelta, y
no de a 1. En este caso, esto significará que el ciclo no efectuará las 50 vueltas sino
sólo 25.
Problema 1:
Realizar un programa que imprima en pantalla los números del 1 al 100.
Diagrama de flujo:
Programa:
Problema 2:
: Desarrollar un programa que permita la carga de 10 valores por teclado y nos muestre
posteriormente la suma de los valores ingresados y su promedio. Este problema ya lo
desarrollamos , lo resolveremos empleando la estructura for.
Diagrama de flujo:
En este caso, a la variable del for (f) sólo se la requiere para que se repita el bloque de
instrucciones 10 veces.
Programa:
import java.util.Scanner;
Problema 3:
Escribir un programa que lea 10 notas de alumnos y nos informe cuántos tienen notas
mayores o iguales a 7 y cuántos menores.
Dentro de la estructura repetitiva debemos hacer la carga de la variable nota y verificar con
una estructura condicional si el contenido de la variable nota es mayor o igual a 7 para
incrementar el contador aprobados, en caso de que la condición retorne falso debemos
incrementar la variable reprobados.
Diagrama de flujo:
Los contadores aprobados y reprobados deben imprimirse FUERA de la estructura
repetitiva.
Es fundamental inicializar los contadores aprobados y reprobados en cero antes de
entrar a la estructura for.
Importante: Un error común es inicializar los contadores dentro de la estructura
repetitiva. En caso de hacer esto los contadores se fijan en cero en cada ciclo del for,
por lo que al finalizar el for como máximo el contador puede tener el valor 1.
Programa:
import java.util.Scanner;
Problema 4:
Escribir un programa que lea 10 números enteros y luego muestre cuántos valores
ingresados fueron múltiplos de 3 y cuántos de 5. Debemos tener en cuenta que hay
números que son múltiplos de 3 y de 5 a la vez.
Diagrama de flujo:
Tengamos en cuenta que el operador matemático % retorna el resto de dividir un valor
por otro, en este caso: valor%3 retorna el resto de dividir el valor que ingresamos por
teclado, por tres.
Veamos: si ingresamos 6 el resto de dividirlo por 3 es 0, si ingresamos 12 el resto de
dividirlo por 3 es 0. Generalizando: cuando el resto de dividir por 3 al valor que
ingresamos por teclado es cero, se trata de un múltiplo de dicho valor.
Ahora bien ¿por qué no hemos dispuesto una estructura if anidada? Porque hay
valores que son múltiplos de 3 y de 5 a la vez. Por lo tanto con if anidados no
podríamos analizar los dos casos.
Es importante darse cuenta cuando conviene emplear if anidados y cuando no debe
emplearse.
Programa:
import java.util.Scanner;
Problema 5:
Diagrama de flujo:
Programa:
import java.util.Scanner;
Problemas propuestos
Ha llegado nuevamente la parte fundamental, que es el momento donde uno desarrolla
individualmente un algoritmo para la resolución de un problema.
6. Escribir un programa que pida ingresar coordenadas (x,y) que representan puntos
en el plano.
Informar cuántos puntos se han ingresado en el primer, segundo, tercer y cuarto
cuadrante. Al comenzar el programa se pide que se ingrese la cantidad de puntos
a procesar.
Solución
Retornar
Listado completo de tutoriales
12 Estructura repetitiva do
while
La estructura do while es otra estructura repetitiva, la cual ejecuta al menos una vez su
bloque repetitivo, a diferencia del while o del for que podían no ejecutar el bloque.
Esta estructura repetitiva se utiliza cuando conocemos de antemano que por lo menos
una vez se ejecutará el bloque repetitivo.
La condición de la estructura está abajo del bloque a repetir, a diferencia del while o del
for que está en la parte superior.
Representación gráfica:
Problema 1:
Escribir un programa que solicite la carga de un número entre 0 y 999, y nos muestre
un mensaje de cuántos dígitos tiene el mismo. Finalizar el programa cuando se cargue
el valor 0.
Diagrama de flujo:
No hay que confundir los rombos de las estructuras condicionales con los de las
estructuras repetitivas do while.
En este problema por lo menos se carga un valor. Si se carga un valor mayor o igual a
100 se trata de un número de tres cifras, si es mayor o igual a 10 se trata de un valor
de dos dígitos, en caso contrario se trata de un valor de un dígito. Este bloque se repite
hasta que se ingresa en la variable valor el número 0 con lo que la condición de la
estructura do while retorna falso y sale del bloque repetitivo finalizando el programa.
Programa:
import java.util.Scanner;
Problema 2:
Diagrama de flujo:
Es importante analizar este diagrama de flujo.
Definimos un contador cant que cuenta la cantidad de valores ingresados por el
operador (no lo incrementa si ingresamos 0)
El valor 0 no es parte de la serie de valores que se deben sumar.
Definimos el acumulador suma que almacena todos los valores ingresados por teclado.
La estructura repetitiva do while se repite hasta que ingresamos el valor 0. Con dicho
valor la condición del ciclo retorna falso y continúa con el flujo del diagrama.
Disponemos por último una estructura condicional para el caso que el operador cargue
únicamente un 0 y por lo tanto no podemos calcular el promedio ya que no existe la
división por 0.
En caso que el contador cant tenga un valor distinto a 0 el promedio se obtiene
dividiendo el acumulador suma por el contador cant que tiene la cantidad de valores
ingresados antes de introducir el 0.
Programa:
import java.util.Scanner;
El contador cant DEBE inicializarse antes del ciclo, lo mismo que el acumulador suma.
El promedio se calcula siempre y cuando el contador cant sea distinto a 0.
Problema 3:
Programa:
import java.util.Scanner;
Problemas propuestos
1. Realizar un programa que acumule (sume) valores ingresados por teclado hasta
ingresar el 9999 (no sumar dicho valor, indica que ha finalizado la carga). Imprimir
el valor acumulado e informar si dicho valor es cero, mayor a cero o menor a cero.
Solución
Retornar
Listado completo de tutoriales
13 Cadenas de caracteres en
Java
En Java hemos visto que cuando queremos almacenar un valor entero definimos una
variable de tipo int, si queremos almacenar un valor con decimales definimos una
variable de tipo float. Ahora si queremos almacenar una cadena de caracteres (por
ejemplo un nombre de una persona) debemos definir un objeto de la clase String.
Problema 1:
Programa:
import java.util.Scanner;
Para almacenar un nombre debemos definir una variable de tipo String y su ingreso por
teclado se hace llamando al método next() del objeto teclado:
nombre1=teclado.next();
La primera salvedad que tenemos que hacer cuando utilizamos el método next() es que
solo nos permite ingresar una cadena de caracteres con la excepción del espacio en
blanco (es decir debemos ingresar un nombre de persona y no su nombre y apellido
separado por un espacio en blanco)
Veamos que existe otro método llamado nextLine() que nos permite cargar espacios en
blanco pero para su uso se complica cuando cargamos otras valores de tipo distinto a
String (por ejemplo int, float etc.)
Problema 2:
Solicitar el ingreso del apellido, nombre y edad de dos personas. Mostrar el nombre de
la persona con mayor edad. Realizar la carga del apellido y nombre en una variable de
tipo String.
Programa:
import java.util.Scanner;
Cuando se ingresa una cadena con caracteres en blanco debemos tener en cuenta en
llamar al método nextLine()
Una dificultad se presenta si llamamos al método nextLine() y previamente hemos
llamado al método nextInt(), esto debido a que luego de ejecutar el método nextInt()
queda almacenado en el objeto de la clase Scanner el caracter "Enter" y si llamamos
inmediatamente al método nextLine() este almacena dicho valor de tecla y continúa con
el flujo del programa. Para solucionar este problema debemos generar un código
similar a:
System.out.print("Ingrese edad:");
edad1=teclado.nextInt();
System.out.print("Ingrese el apellido y el nombre:");
teclado.nextLine();
apenom2=teclado.nextLine();
Como vemos llamamos al método nextLine() dos veces, la primera retorna la tecla
"Enter" y la segunda se queda esperando que ingresemos el apellido y nombre (tener
en cuenta que esto es necesario solo si previamente se llamó al método nextInt() o
nextFloat().
Problema 3:
Programa:
import java.util.Scanner;
if (apellido1.equals(apellido2)) {
El método equals retorna verdadero si los contenidos de los dos String son
exactamente iguales, esto hace que se ejecute el bloque del verdadero.
Recordemos que hemos utilizado el método next() para la carga de los String, luego
esto hace que no podamos ingresar un apellido con espacios en blanco (podemos
probar que si ingresamos por ejemplo "Rodriguez Rodriguez" en el primer apellido,
luego se carga la cadena "Rodriguez" en la variable apellido1 y "Rodriguez" en la
variable apellido2 (con esto hacemos notar que cada vez que ingresamos un espacio
en blanco cuando utilizamos el método next() los caracteres que siguen al espacio en
blanco son recuperados en la siguiente llamada al método next())
El método equals retorna verdadero si los contenidos de los dos String son
exactamente iguales, es decir si cargamos "Martinez" en apellido1 y "martinez" en
apellido2 luego el método equals retorna falso ya que no es lo mismo la "M" mayúscula
y la "m" minúscula.
if (apellido1.equalsIgnoreCase(apellido2)) {
System.out.print("Los apellidos son iguales sin tener e
} else {
System.out.print("Los apellidos son distintos sin tener
}
Retornar
Listado completo de tutoriales
14 Declaración de una clase y
definición de objetos.
Una clase es un molde del que luego se pueden crear múltiples objetos, con similares
características.
Una clase es una plantilla (molde), que define atributos (variables) y métodos
(funciones)
La clase define los atributos y métodos comunes a los objetos de ese tipo, pero luego,
cada objeto tendrá sus propios valores y compartirán las mismas funciones.
Debemos crear una clase antes de poder crear objetos (instancias) de esa clase. Al
crear un objeto de una clase, se dice que se crea una instancia de la clase o un objeto
propiamente dicho.
Problema 1:
Confeccionar una clase que permita carga el nombre y la edad de una persona.
Mostrar los datos cargados. Imprimir un mensaje si es mayor de edad (edad>=18)
Programa:
import java.util.Scanner;
public class Persona {
private Scanner teclado;
private String nombre;
private int edad;
El nombre de la clase debe hacer referencia al concepto (en este caso la hemos
llamado Persona):
Veremos más adelante que un atributo es normalmente definido con la cláusula private
(con esto no permitimos el acceso al atributo desde otras clases)
A los atributos se tiene acceso desde cualquier función o método de la clase (salvo la
main)
Luego de definir los atributos de la clase debemos declarar los métodos o funciones de
la clase. La sintaxis es parecida a la main (sin la cláusula static):
Problema 2:
Programa:
import java.util.Scanner;
public class Triangulo {
private Scanner teclado;
private int lado1,lado2,lado3;
Todos los problemas que requieran la entrada de datos por teclado debemos definir un
atributo de la clase Scanner:
Este problema requiere definir tres atributos de tipo entero donde almacenamos los
valores de los lados del triángulo:
Como podemos observar cuando un problema se vuelve más complejo es más fácil y
ordenado separar los distintos algoritmos en varios métodos y no codificar todo en la
main.
El último método de esta clase verifica si los tres enteros ingresados son iguales:
Desarrollar una clase que represente un punto en el plano y tenga los siguientes
métodos: cargar los valores de x e y, imprimir en que cuadrante se encuentra dicho
punto (concepto matemático, primer cuadrante si x e y son positivas, si x<0 e y>0
segundo cuadrante, etc.)
Programa:
import java.util.Scanner;
public class Punto {
private Scanner teclado;
int x,y;
void imprimirCuadrante() {
if (x>0 && y>0) {
System.out.print("Se encuentra en el primer cuadrante.");
} else {
if (x<0 && y>0) {
System.out.print("Se encuentra en el segundo cuadrante.");
} else {
if (x<0 && y<0) {
System.out.print("Se encuentra en el tercer
cuadrante.");
} else {
if (x>0 && y<0) {
System.out.print("Se encuentra en el cuarto
cuadrante.");
} else {
System.out.print("El punto no está en un
cuadrante.");
}
}
}
}
}
Definimos tres atributos (el objeto de la clase Scanner y los dos enteros donde
almacenamos la coordenada x e y del punto:
private Scanner teclado;
int x,y;
El método inicializar crea el objeto de la clase Scanner y pide cargar las coordenadas x
e y:
void imprimirCuadrante() {
if (x>0 && y>0) {
System.out.print("Se encuentra en el primer cuadrante.");
} else {
if (x<0 && y>0) {
System.out.print("Se encuentra en el segundo cuadrante.");
} else {
if (x<0 && y<0) {
System.out.print("Se encuentra en el tercer
cuadrante.");
} else {
if (x>0 && y<0) {
System.out.print("Se encuentra en el cuarto
cuadrante.");
} else {
System.out.print("El punto no está en un
cuadrante.");
}
}
}
}
}
Desarrollar una clase que represente un Cuadrado y tenga los siguientes métodos:
cargar el valor de su lado, imprimir su perímetro y su superficie.
Programa:
import java.util.Scanner;
public class Cuadrado {
private Scanner teclado;
int lado;
Problemas propuestos
1. Confeccionar una clase que represente un empleado. Definir como atributos su
nombre y su sueldo. Confeccionar los métodos para la carga, otro para imprimir
sus datos y por último uno que imprima un mensaje si debe pagar impuestos (si el
sueldo supera a 3000)
Solución
Retornar
Listado completo de tutoriales
15 Declaración de métodos.
Cuando uno plantea una clase en lugar de especificar todo el algoritmo en un único
método (lo que hicimos en los primeros pasos de este tutorial) es dividir todas las
responsabilidades de las clase en un conjunto de métodos.
Los parámetros los podemos imaginar como variables locales al método, pero su valor
se inicializa con datos que llegan cuando lo llamamos.
Problema 1:
Confeccionar una clase que permita ingresar valores enteros por teclado y nos muestre
la tabla de multiplicar de dicho valor. Finalizar el programa al ingresar el 1.
Programa:
import java.util.Scanner;
public class TablaMultiplicar {
public void cargarValor() {
Scanner teclado=new Scanner(System.in);
int valor;
do {
System.out.print("Ingrese valor:");
valor=teclado nextInt();
valor=teclado.nextInt();
if (valor!=-1) {
calcular(valor);
}
} while (valor!=-1);
}
En esta clase no hemos definido ningún atributo, ya que el objeto de la clase Scanner
lo requerimos en un solo método, por ello lo definimos como una variable local.
El método calcular recibe un parámetro de tipo entero, luego lo utilizamos dentro del
método para mostrar la tabla de multiplicar de dicho valor, para esto inicializamos la
variable f con el valor que llega en el parámetro. Luego de cada ejecución del for
incrementamos el contador f con el valor de v.
El método cargarValores no tiene parámetros y tiene por objetivo cargar un valor entero
por teclado y llamar al método calcular para que muestre la tabla de multiplicar del
valor que le pasamos por teclado:
public void cargarValor() {
Scanner teclado=new Scanner(System.in);
int valor;
do {
System.out.print("Ingrese valor:");
valor=teclado.nextInt();
if (valor!=-1) {
calcular(valor);
}
} while (valor!=-1);
}
Cuando un método retorna un dato en vez de indicar la palabra clave void previo al
nombre del método indicamos el tipo de dato que retorna. Luego dentro del algoritmo
en el momento que queremos que finalice el mismo y retorne el dato empleamos la
palabra clave return con el valor respectivo.
Problema 2:
Confeccionar una clase que permita ingresar tres valores por teclado. Luego mostrar el
mayor y el menor.
Programa:
import java.util.Scanner;
public class MayorMenor {
public void cargarValores() {
Scanner teclado=new Scanner(System.in);
System.out.print("Ingrese primer valor:");
int valor1=teclado.nextInt();
System.out.print("Ingrese segundo valor:");
int valor2=teclado.nextInt();
System.out.print("Ingrese tercer valor:");
int valor3=teclado.nextInt();
int mayor,menor;
mayor=calcularMayor(valor1,valor2,valor3);
menor=calcularMenor(valor1,valor2,valor3);
System.out.println("El valor mayor de los tres
System.out.println("El valor menor de los tres
}
Si vemos la sintaxis que calcula el mayor de tres valores enteros es similar al algoritmo
visto en conceptos anteriores:
Lo primero que podemos observar que el método retorna un entero y recibe tres
parámetros:
Dentro del método verificamos cual de los tres parámetros almacena un valor mayor, a
este valor lo almacenamos en una variable local llamada "m", al valor almacenado en
esta variable lo retornamos al final con un return.
mayor=calcularMayor(valor1,valor2,valor3);
Debemos asignar a una variable el valor devuelto por el método calcularMayor. Luego
el contenido de la variable mayor lo mostramos:
Retornar
Listado completo de tutoriales
16 Estructura de datos tipo
vector.
Problema 1:
Programa:
import java.util.Scanner;
public class PruebaVector1 {
private Scanner teclado;
private int[] sueldos;
En el método de cargar lo primero que hacemos es crear el vector (en java los vectores
son objetos por lo que es necesario proceder a su creación mediante el operador new):
sueldos=new int[5];
Para cargar cada componente debemos indicar entre corchetes que elemento del
vector estamos accediendo:
for(int f=0;f<5;f++) {
System.out.print("Ingrese valor de la componente:");
sueldos[f]=teclado.nextInt();
}
La estructura de programación que más se adapta para cargar en forma completa las
componentes de un vector es un for, ya que sabemos de antemano la cantidad de
valores a cargar.
Cuando f vale cero estamos accediendo a la primer componente del vector (en nuestro
caso sería):
sueldos[0]=teclado.nextInt();
Lo mas común es utilizar una estructura repetitiva for para recorrer cada componente
del vector.
Utilizar el for nos reduce la cantidad de código, si no utilizo un for debería en forma
secuencial implementar el siguiente código:
Siempre que queremos acceder a una componente del vector debemos indicar entre
corchetes la componente, dicho valor comienza a numerarse en cero y continua hasta
un número menos del tamaño del vector, en nuestro caso creamos el vector con 5
elementos:
sueldos=new int[5];
Problema 2:
Programa:
import java.util.Scanner;
public class PruebaVector2 {
private Scanner teclado;
private float[] alturas;
private float promedio;
alturas=new float[5];
Procedemos seguidamente a cargar todos sus elementos:
for(int f=0;f<5;f++) {
System.out.print("Ingrese la altura de la persona:");
alturas[f]=teclado.nextFloat();
}
Por último en un tercer método comparamos cada componente del vector con el
atributo promedio, si el valor almacenado supera al promedio incrementamos un
contador en caso que sea menor al promedio incrementamos otro contador:
Importante:
En este problema podemos observar una ventaja de tener almacenadas todas las
alturas de las personas. Si no conociéramos los vectores tenemos que cargar otra vez
las alturas por teclado para compararlas con el promedio.
Mientras el programa está en ejecución tenemos el vector alturas a nuestra disposición.
Es importante tener en cuenta que cuando finaliza la ejecución del programa se pierde
el contenido de todas las variables (simples y vectores)
Problema 3:
Una empresa tiene dos turnos (mañana y tarde) en los que trabajan 8 empleados (4
por la mañana y 4 por la tarde)
Confeccionar un programa que permita almacenar los sueldos de los empleados
agrupados por turno.
Imprimir los gastos en sueldos de cada turno.
Programa:
import java.util.Scanner;
public class PruebaVector3 {
private Scanner teclado;
private float[] turnoMan;
private float[] turnoTar;
turnoMan=new float[4];
turnoTar=new float[4];
En otro método procedemos a sumar las componentes de cada vector y mostrar dichos
acumuladores:
float man=0;
float tar=0;
for(int f=0;f<4;f++){
man=man+turnoMan[f];
tar=tar+turnoTar[f];
}
System.out.println("Total de gastos del turno de la mañana:"+man);
System.out.println("Total de gastos del turno de la tarde:"+tar);
Problemas propuestos
1. Desarrollar un programa que permita ingresar un vector de 8 elementos, e informe:
El valor acumulado de todos los elementos del vector.
El valor acumulado de los elementos del vector que sean mayores a 36.
Cantidad de valores mayores a 50.
3. Se tienen las notas del primer parcial de los alumnos de dos cursos, el curso A y el
curso B, cada curso cuenta con 5 alumnos.
Realizar un programa que muestre el curso que obtuvo el mayor promedio general.
Solución
Retornar
Listado completo de tutoriales
17 Vector (Tamaño de un
vector)
Como hemos visto cuando se crea un vector indicamos entre corchetes su tamaño:
sueldos=new int[5];
Luego cuando tenemos que recorrer dicho vector disponemos una estructura repetitiva
for:
for(int f=0;f<5;f++) {
System.out.print("Ingrese valor de la componente:");
sueldos[f]=teclado.nextInt();
}
Como vemos el for se repite mientras el contador f vale menos de 5. Este estructura
repetitiva es idéntica cada vez que recorremos el vector.
Que pasa ahora si cambiamos el tamaño del vector cuando lo creamos:
sueldos=new int[7];
Con esto tenemos que cambiar todos los for que recorren dicho vector. Ahora veremos
que un vector al ser un objeto tiene un atributo llamado length que almacena su
tamaño. Luego podemos modificar todos los for con la siguiente sintaxis:
for(int f=0;f<sueldos.length;f++) {
System.out.print("Ingrese valor de la componente:");
sueldos[f]=teclado.nextInt();
}
También podemos pedir al usuario que indique el tamaño del vector en tiempo de
ejecución, en estos casos se hace imprescindible el empleo del atributo length.
Problema 1:
import java.util.Scanner;
public class PruebaVector8 {
private Scanner teclado;
private int[] sueldos;
Luego para la creación del mismo ingresamos una variable entera y la utilizamos como
subíndice en el momento de la creación del vector:
System.out.print("Cuantos sueldos cargará:");
int cant;
cant=teclado.nextInt();
sueldos=new int[cant];
Luego las estructuras repetitivas las acotamos accediendo al atributo length del vector:
for(int f=0;f<sueldos.length;f++) {
System.out.print("Ingrese sueldo:");
sueldos[f]=teclado.nextInt();
}
Problemas propuestos
1. Desarrollar un programa que permita ingresar un vector de n elementos, ingresar n
por teclado. Luego imprimir la suma de todos sus elementos
Solución
Retornar
Listado completo de tutoriales
18 Vectores paralelos
Este concepto se da cuando hay una relación entre las componentes de igual
subíndice (misma posición) de un vector y otro.
Si tenemos dos vectores de 5 elementos cada uno. En uno se almacenan los nombres
de personas en el otro las edades de dichas personas.
Decimos que el vector nombres es paralelo al vector edades si en la componente 0 de
cada vector se almacena información relacionada a una persona (Juan 12 años)
Es decir hay una relación entre cada componente de los dos vectores.
Problema 1:
Programa:
import java.util.Scanner;
public class PruebaVector10 {
private Scanner teclado;
private String[] nombres;
private int[] edades;
nombres=new String[5];
edades=new int[5];
for(int f=0;f<nombres.length;f++) {
System.out.print("Ingrese nombre:");
nombres[f]=teclado.next();
System.out.print("Ingrese edad:");
edades[f]=teclado.nextInt();
}
Podemos utilizar el length de cualquiera de los dos vectores, ya que tienen el mismo
tamaño.
Para imprimir los nombres de las personas mayores de edad verificamos cada
componente del vector de edades, en caso que sea igual o mayor o 18 procedemos a
mostrar el elemento de la misma posición del otro vector:
for(int f=0;f<nombres.length;f++) {
if (edades[f]>=18) {
System.out.println(nombres[f]);
}
}
Retornar
Listado completo de tutoriales
19 Vectores (mayor y menor
elemento)
Problema 1:
Programa:
import java.util.Scanner;
public class PruebaVector11 {
private Scanner teclado;
private String[] nombres;
private float[] sueldos;
Definimos los dos vectores paralelos donde almacenaremos los nombres y los sueldos
de los operarios:
nombres=new String[5];
sueldos=new float[5];
for(int f=0;f<nombres.length;f++) {
System.out.print("Ingrese el nombre del empleado:");
nombres[f]=teclado.next();
System.out.print("Ingrese el sueldo:");
sueldos[f]=teclado.nextFloat();
}
Para obtener el mayor sueldo y el nombre del operario realizar los siguientes pasos:
Inicializamos una variable mayor con la primer componente del vector sueldos:
mayor=sueldos[0];
Inicializamos una variable pos con el valor 0, ya que decimos primeramente que el
mayor es la primer componente del vector:
pos=0;
for(int f=1;f<nombres.length;f++) {
Accedemos a cada componente para controlar si supera lo que tiene la variable mayor:
if (sueldos[f]>mayor) {
En caso de ser verdadera la condición asignamos a la variable mayor este nuevo valor
sueldos[f]
mayor=sueldos[f];
pos=f
Problemas propuestos
1. Cargar un vector de n elementos. imprimir el menor y un mensaje si se repite
dentro del vector.
Solución
Retornar
Listado completo de tutoriales
20 Vectores (ordenamiento)
Se puede ordenar tanto vectores con componentes de tipo int, float como String. En
este último caso el ordenamiento es alfabético.
Problema 1:
Esta primera aproximación tiene por objetivo analizar los intercambios de elementos
dentro del vector.
El algoritmo consiste en comparar si la primera componente es mayor a la segunda, en
caso que la condición sea verdadera, intercambiamos los contenidos de las
componentes.
1200
750
820
550
490
En este ejemplo: ¿es 1200 mayor a 750? La respuesta es verdadera, por lo tanto
intercambiamos el contenido de la componente 0 con el de la componente 1.
Luego comparamos el contenido de la componente 1 con el de la componente 2: ¿Es
1200 mayor a 820?
La respuesta es verdadera entonces intercambiamos.
Si hay 5 componentes hay que hacer 4 comparaciones, por eso el for se repite 4 veces.
Generalizando: si el vector tiene N componentes hay que hacer N1 comparaciones.
Cuando f = 0 f = 1 f = 2 f =
Podemos ver cómo el valor más grande del vector desciende a la última componente.
Empleamos una variable auxiliar (aux) para el proceso de intercambio:
aux=sueldos[f];
sueldos[f]=sueldos[f+1];
sueldos[f+1]=aux;
750
820
550
490
1200
Analizando el algoritmo podemos comprobar que el elemento mayor del vector se ubica
ahora en el último lugar.
Podemos definir otros vectores con distintos valores y comprobar que siempre el
elemento mayor queda al final.
Pero todavía con este algoritmo no se ordena un vector. Solamente está ordenado el
último elemento del vector.
Ahora bien, con los 4 elementos que nos quedan podemos hacer el mismo proceso
visto anteriormente, con lo cual quedará ordenado otro elemento del vector. Este
proceso lo repetiremos hasta que quede ordenado por completo el vector.
Como debemos repetir el mismo algoritmo podemos englobar todo el bloque en otra
estructura repetitiva.
Cuando k = 0
f = 0 f = 1 f = 2 f =
750 750 750 750
1200 820 820 820
820 1200 550 550
550 550 1200 490
490 490 490 120
Cuando k = 1
f = 0 f = 1 f = 2 f =
750 750 750 750
820 550 550 550
550 820 490 490
490 490 820 820
1200 1200 1200 120
Cuando k = 2
f = 0 f = 1 f = 2 f =
550 550 550 550
750 490 490 490
490 750 750 750
820 820 820 820
1200 1200 1200 120
Cuando k = 3
f = 0 f = 1 f = 2 f =
490 490 490 490
550 550 550 550
750 750 750 750
820 820 820 820
1200 1200 1200 120
Si observamos, cuando quedan dos elementos por ordenar, al ordenar uno de ellos
queda el otro automáticamente ordenado (podemos imaginar que si tenemos un vector
con 2 elementos no se requiere el for externo, porque este debería repetirse una única
vez)
Ejemplo: En la primera ejecución del for interno el valor 1200 queda ubicado en la
posición 4 del vector. En la segunda ejecución comparamos si el 820 es mayor a 1200,
lo cual seguramente será falso.
Podemos concluir que la primera vez debemos hacer para este ejemplo 4
comparaciones, en la segunda ejecución del for interno debemos hacer 3
comparaciones y en general debemos ir reduciendo en uno la cantidad de
comparaciones.
Si bien el algoritmo planteado funciona, un algoritmo más eficiente, que se deriva del
anterior es el plantear un for interno con la siguiente estructura: (f=0 ; f<4k; f++)
Es decir restarle el valor del contador del for externo.
Programa:
import java.util.Scanner;
public class PruebaVector13 {
private Scanner teclado;
private int[] sueldos;
También podemos ordenar vectores cuyas componentes sean de tipo String. Para esto
no podemos utilizar el operador > sino debemos utilizar un método de la clase String:
String cad1="juan";
String cad2="analia";
if (cad1.compareTo(cad2)>0)
{
System.out.println(cad1 + " es mayor alfabéticamente que " + cad2
}
Si los dos String son exactamente iguales el método compareTo retorna un cero, y
finalmente si cad1 es menor alfabeticamente retorna un valor menor a cero.
Problema 2:
Programa:
import java.util.Scanner;
public class PruebaVector14 {
private Scanner teclado;
private String[] paises;
paises=new String[5];
for(int f=0;f<paises.length;f++) {
System.out.print("Ingrese el nombre del pais:");
paises[f]=teclado.next();
}
if (paises[f].compareTo(paises[f+1])>0) {
String aux;
aux=paises[f];
paises[f]=paises[f+1];
paises[f+1]=aux;
Problemas propuestos
1. Cargar un vector de n elementos de tipo entero. Ordenar posteriormente el vector.
Solución
Retornar
21 Vectores (ordenamiento con Listado completo de tutoriales
vectores paralelos)
Cuando se tienen vectores paralelos y se ordena uno de ellos hay que tener la
precaución de intercambiar los elementos de los vectores paralelos.
Problema 1:
Confeccionar un programa que permita cargar los nombres de 5 alumnos y sus notas
respectivas. Luego ordenar las notas de mayor a menor. Imprimir las notas y los
nombres de los alumnos.
Programa:
import java.util.Scanner;
public class PruebaVector16 {
private Scanner teclado;
private String[] nombres;
private int[] notas;
Creamos los dos vectores paralelos con cinco elementos cada uno:
nombres=new String[5];
notas=new int[5];
for(int k=0;k<notas.length;k++) {
for(int f=0;f<notas.length-1-k;f++) {
if (notas[f]<notas[f+1]) {
En el caso que la nota de la posición 'f' sea menor a de la posición siguiente 'f+1'
procedemos a intercambiar las notas:
int auxnota;
auxnota=notas[f];
notas[f]=notas[f+1];
notas[f+1]=auxnota;
String auxnombre;
auxnombre=nombres[f];
nombres[f]=nombres[f+1];
nombres[f+1]=auxnombre;
Como vemos utilizamos dos auxiliares distintos porque los elementos de los dos
vectores son de distinto tipo (int y String)
Problemas propuestos
1. Cargar en un vector los nombres de 5 paises y en otro vector paralelo la cantidad
de habitantes del mismo. Ordenar alfabéticamente e imprimir los resultados. Por
último ordenar con respecto a la cantidad de habitantes (de mayor a menor) e
imprimir nuevamente.
Solución
Retornar
Listado completo de tutoriales
22 Estructura de datos tipo
matriz
Una matriz es una estructura de datos que permite almacenar un CONJUNTO de datos
del MISMO tipo.
Con un único nombre se define la matriz y por medio de DOS subíndices hacemos
referencia a cada elemento de la misma (componente)
Hemos graficado una matriz de 3 filas y 5 columnas. Para hacer referencia a cada
elemento debemos indicar primero la fila y luego la columna, por ejemplo en la
componente 1,4 se almacena el valor 97.
En este ejemplo almacenamos valores enteros. Todos los elementos de la matriz
deben ser del mismo tipo (int, float, String etc.)
Las filas y columnas comienzan a numerarse a partir de cero, similar a los vectores.
Una matriz se la puede representar por un conjunto de vectores.
Problema 1:
Crear una matriz de 3 filas por 5 columnas con elementos de tipo int, cargar sus
componentes y luego imprimirlas.
Programa:
import java.util.Scanner;
public class Matriz1 {
private Scanner teclado;
private int[][] mat;
public void cargar() {
teclado=new Scanner(System.in);
mat=new int[3][5];
for(int f=0;f<3;f++) {
for(int c=0;c<5;c++) {
System.out.print("Ingrese componente:")
mat[f][c]=teclado.nextInt();
}
}
}
Para definir una matriz debemos antecederle los corchetes abiertos y cerrados dos
veces:
De esta forma el compilador de Java puede diferenciar los vectores de las matrices.
Para crear la matriz, es decir hacer la reserva de espacio de todas sus componentes
debemos utilizar el operador new y mediante dos subíndices indicamos la cantidad de
filas y columnas que tendrá la matriz:
mat=new int[3][5];
Luego debemos pasar a cargar sus 15 componentes (cada fila almacena 5
componentes y tenemos 3 filas)
Lo más cómodo es utilizar un for anidado, el primer for que incrementa el contador f lo
utilizamos para recorrer las filas y el contador interno llamado c lo utilizamos para
recorrer las columnas.
Cada vez que se repite en forma completa el for interno se carga una fila completa,
primero se carga la fila cero en forma completa, luego la fila uno y finalmente la fila 2.
Siempre que accedemos a una posición de la matriz debemos disponer dos subíndices
que hagan referencia a la fila y columna mat[f][c]):
for(int f=0;f<3;f++) {
for(int c=0;c<5;c++) {
System.out.print("Ingrese componente:");
mat[f][c]=teclado.nextInt();
}
}
Para imprimir la matriz de forma similar utilizamos dos for para acceder a cada
elemento de la matriz:
for(int f=0;f<3;f++) {
for(int c=0;c<5;c++) {
System.out.print(mat[f][c]+" ");
}
System.out.println();
}
}
Cada vez que se ejecuta todas las vueltas del for interno tenemos en pantalla una fila
completa de la matriz, por eso pasamos a ejecutar un salto de línea (con esto logramos
que en pantalla los datos aparezcan en forma matricial):
System.out.println();
Problema 2:
Crear y cargar una matriz de 4 filas por 4 columnas. Imprimir la diagonal principal.
x - - -
- x - -
- - x -
- - - x
Programa:
import java.util.Scanner;
public class Matriz2 {
private Scanner teclado;
private int[][] mat;
for(int k=0;k<4;k++) {
System.out.print(mat[k][k]+" ");
}
Problema 3:
Crear y cargar una matriz de 3 filas por 4 columnas. Imprimir la primer fila. Imprimir la
última fila e imprimir la primer columna.
Programa:
import java.util.Scanner;
public class Matriz3 {
private Scanner teclado;
private int[][] mat;
mat=new int[3][4];
Luego de cargarla el primer método que codificamos es el que imprimime la primer fila.
Disponemos un for para recorrer las columnas, ya que la fila siempre será la cero.
Como son cuatro los elementos de la primer fila el for se repite esta cantidad de veces:
Para imprimir la última fila el algoritmo es similar, disponemos un for que se repita 4
veces y en el subíndice de la fila disponemos el valor 2 (ya que la matriz tiene 3 filas):
Para imprimir la primer columna el for debe repetirse 3 veces ya que la matriz tiene 3
filas. Dejamos constante el subíndice de la columna con el valor cero:
System.out.println("Primer columna:");
for(int f=0;f<3;f++) {
System.out.println(mat[f][0]);
}
Problemas propuestos
1. Crear una matriz de 2 filas y 5 columnas. Realizar la carga de componentes por
columna (es decir primero ingresar toda la primer columna, luego la segunda
columna y así sucesivamente)
Imprimir luego la matriz.
Solución
Retornar
Listado completo de tutoriales
23 Matrices (cantidad de filas y
columnas)
Como hemos visto para definir y crear la matriz utilizamos la siguiente sintaxis:
int[][] mat;
Creación:
mat=new int[3][4];
Como las matrices son objetos en Java disponemos por un lado del atributo length que
almacena la cantidad de filas de la matriz:
Problema 1:
Crear una matriz de n * m filas (cargar n y m por teclado) Imprimir la matriz completa y
la última fila.
Programa:
import java.util.Scanner;
public class Matriz5 {
private Scanner teclado;
private int[][] mat;
En este ejemplo cada vez que se ejecute el programa el tamaño de la matriz lo define
el usuario, para ello ingresamos por teclado dos enteros y seguidamente procedemos a
crear la matriz con dichos valores:
for(int f=0;f<mat.length;f++) {
for(int c=0;c<mat[f].length;c++) {
System.out.print("Ingrese componente:");
mat[f][c]=teclado.nextInt();
}
}
El algoritmo de impresión es idéntico al visto anteriormente con la modificación de las
condiciones de los for:
Para imprimir la última fila debemos disponer un valor fijo en el subíndice de la fila (en
este caso no podemos disponer un número fijo sino preguntarle a la misma matriz la
cantidad de filas y restarle uno ya que las filas comienzan a numerarse a partir de cero:
mat[mat.length1][c])
También la condición del for debemos acceder al atributo length de la última fila
mat[mat.length1].length
for(int c=0;c<mat[mat.length-1].length;c++) {
System.out.print(mat[mat.length-1][c]+" ");
}
Problema 2:
Crear una matriz de n * m filas (cargar n y m por teclado) Imprimir el mayor elemento y
la fila y columna donde se almacena.
Programa:
import java.util.Scanner;
public class Matriz6 {
private Scanner teclado;
private int[][] mat;
int mayor=mat[0][0];
int filamay=0;
int columnamay=0;
Luego mediante dos for recorremos todos los elementos de la matriz y cada vez que
encontramos un elemento mayor al actual procedemos a actualizar la variable mayor y
la posición donde se almacena:
for(int f=0;f<mat.length;f++) {
for(int c=0;c<mat[f].length;c++) {
if (mat[f][c]>mayor) {
mayor=mat[f][c];
filamay=f;
columnamay=c;
}
}
}
Problemas propuestos
1. Crear una matriz de n * m filas (cargar n y m por teclado) Intercambiar la primer fila
con la segundo. Imprimir luego la matriz.
2. Crear una matriz de n * m filas (cargar n y m por teclado) Imprimir los cuatro
valores que se encuentran en los vértices de la misma (mat[0][0] etc.)
Solución
Retornar
24 Matrices y vectores paralelos Listado completo de tutoriales
Problema 1:
Programa:
import java.util.Scanner;
public class Matriz9 {
private Scanner teclado;
private String[] empleados;
private int[][] sueldos;
private int[] sueldostot;
Para resolver este problema lo primero que hacemos es definir una matriz donde se
almacenarán los sueldos mensuales de cada empleado, un vector de tipo String donde
almacenaremos los nombre de cada empleado y finalmente definimos un vector paralelo
a la matriz donde almacenaremos la suma de cada fila de la matriz:
empleados=new String[4];
sueldos=new int[4][3];
for(int f=0;f<empleados.length;f++){
System.out.print("Ingrese el nombre del empleado:");
empleados[f]=teclado.next();
for(int c=0;c<sueldos[f].length;c++) {
System.out.print("Ingrese sueldo:");
sueldos[f][c]=teclado.nextInt();
}
}
El método sumar sueldos crea el vector donde se almacenará la suma de cada fila de la
matriz. Mediante dos for recorremos toda la matriz y sumamos cada fila:
sueldostot=new int[4];
for(int f=0;f<sueldos.length;f++) {
int suma=0;
for(int c=0;c<sueldos[f].length;c++) {
suma=suma+sueldos[f][c];
}
sueldostot[f]=suma;
}
El método imprimirTotalPagado tiene por objetivo mostrar los dos vectores (el de nombre
de los empleados y el que almacena la suma de cada fila de la matriz):
for(int f=0;f<sueldostot.length;f++) {
System.out.println(empleados[f]+" - "+sueldostot[f]);
}
Por último para obtener el nombre del empleado con mayor sueldo acumulado debemos
inicializar dos variables auxiliares con el primer elemento del vector de empleados y en
otra auxiliar guardamos la primer componente del vector sueldostot:
int may=sueldostot[0];
String nom=empleados[0];
for(int f=0;f<sueldostot.length;f++) {
if (sueldostot[f]>may) {
may=sueldostot[f];
nom=empleados[f];
}
}
System.out.println("El empleado con mayor sueldo es "+ nom + " que
tiene un sueldo de "+may);
Problemas propuestos
1. Se desea saber la temperatura media trimestral de cuatro paises. Para ello se tiene
como dato las temperaturas medias mensuales de dichos paises.
Se debe ingresar el nombre del país y seguidamente las tres temperaturas medias
mensuales.
Seleccionar las estructuras de datos adecuadas para el almacenamiento de los datos
en memoria.
a Cargar por teclado los nombres de los paises y las temperaturas medias
mensuales.
b Imprimir los nombres de las paises y las temperaturas medias mensuales de las
mismas.
c Calcular la temperatura media trimestral de cada país.
c Imprimr los nombres de las provincias y las temperaturas medias trimestrales.
b Imprimir el nombre de la provincia con la temperatura media trimestral mayor.
Solución
Retornar
Listado completo de tutoriales
25 Matrices irregulares
Java nos permite crear matrices irregulares. Se dice que una matriz es irregular si la
cantidad de elementos de cada fila varía. Luego podemos imaginar una matriz
irregular:
Como podemos ver la fila cero tiene reservado dos espacios, la fila uno reserva cuatro
espacios y la última fila reserva espacio para tres componentes.
Para crear la matriz irregular del gráfico:
Primero creamos la cantidad de filas dejando vacío el espacio que indica la cantidad de
columnas:
mat=new int[3][];
mat[0]=new int[2];
mat[1]=new int[4];
mat[2]=new int[3];
Luego la forma para acceder a sus componentes es similar a las matrices regulares,
siempre teniendo en cuenta y validando que exista dicha componente:
mat[0][0]=120;
Dará un error si queremos cargar la tercer componente de la fila cero (esto debido a
que no existe):
mat[0][2]=230;
Sytem.out.println(mat.length);
Problema 1:
Confeccionaremos un programa que permita crear una matriz irregular y luego imprimir
la matriz en forma completa.
Programa:
import java.util.Scanner;
public class MatrizIrregular1 {
private Scanner teclado;
private int[][] mat;
Primero creamos la cantidad de filas que tendrá la matriz (en los corchetes para las
columnas no disponemos valor):
Dentro del primer for pedimos que ingrese la cantidad de elementos que tendrá cada
fila y utilizamos el operador new nuevamente, pero en este caso se están creando cada
fila de la matriz (Java trata a cada fila como un vector):
for(int f=0;f<mat.length;f++) {
System.out.print("Cuantas elementos tiene la fila " + f + ":");
int elementos=teclado.nextInt();
mat[f]=new int[elementos];
Dentro del for interno hacemos la carga de las componentes propiamente dicho de la
matriz (podemos ir cargando cada fila a medida que las vamos creando):
for(int c=0;c<mat[f].length;c++) {
System.out.print("Ingrese componente:");
mat[f][c]=teclado.nextInt();
}
Luego imprimimos la matriz en forma completa teniendo cuidado las condiciones que
disponemos en cada for.
El primer for se repite tantas veces como filas tiene la matriz: f<mat.length y
el for interno se repite tantas veces como elementos tiene la fila que estamos
procesando c<mat [f].length:
for(int f=0;f<mat.length;f++) {
for(int c=0;c<mat[f].length;c++) {
System.out.print(mat[f][c]+" ");
}
System.out.println();
}
Problemas propuestos
1. Confeccionar una clase para administrar una matriz irregular de 5 filas y 1 columna
la primer fila, 2 columnas la segunda fila y así sucesivamente hasta 5 columnas la
última fila (crearla sin la intervención del operador)
Realizar la carga por teclado e imprimir posteriormente.
2. Confeccionar una clase para administrar los días que han faltado los 3 empleados
de una empresa.
Definir un vector de 3 elementos de tipo String para cargar los nombres y una
matriz irregular para cargar los días que han faltado cada empleado (cargar el
número de día que faltó)
Cada fila de la matriz representan los días de cada empleado.
Mostrar los empleados con la cantidad de inasistencias.
Cuál empleado faltó menos días.
Solución
Retornar
Listado completo de tutoriales
26 Constructor de la clase
Problema 1:
Programa:
import java.util.Scanner;
public class Operarios {
private Scanner teclado;
private int[] sueldos;
public Operarios()
{
teclado=new Scanner(System.in);
sueldos=new int[5];
for(int f=0;f<5;f++) {
System.out.print("Ingrese valor de la compo
sueldos[f]=teclado.nextInt();
}
}
public void imprimir() {
for(int f=0;f<5;f++) {
System.out.println(sueldos[f]);
}
}
Como podemos ver es el mismo problema que resolvimos cuando vimos vectores. La
diferencia es que hemos sustituido el método cargar con el constructor:
public Operarios()
{
teclado=new Scanner(System.in);
sueldos=new int[5];
for(int f=0;f<5;f++) {
System.out.print("Ingrese valor de la componente:");
sueldos[f]=teclado.nextInt();
}
}
op.imprimir();
Problema 2:
Plantear una clase llamada Alumno y definir como atributos su nombre y su edad. En el
constructor realizar la carga de datos. Definir otros dos métodos para imprimir los datos
ingresados y un mensaje si es mayor o no de edad (edad >=18)
Programa:
import java.util.Scanner;
public class Alumno {
private Scanner teclado;
private String nombre;
private int edad;
public Alumno() {
teclado=new Scanner(System.in);
System.out.print("Ingrese nombre:");
nombre=teclado.next();
System.out.print("Ingrese edad:");
edad=teclado.nextInt();
}
public Alumno() {
teclado=new Scanner(System.in);
System.out.print("Ingrese nombre:");
nombre=teclado.next();
System.out.print("Ingrese edad:");
edad=teclado.nextInt();
}
Los otros dos métodos deben llamarse por su nombre y en el orden que necesitemos:
alumno1.imprimir();
alumno1.esMayorEdad();
Problemas propuestos
1. Confeccionar una clase que represente un empleado. Definir como atributos su
nombre y su sueldo. En el constructor cargar los atributos y luego en otro método
imprimir sus datos y por último uno que imprima un mensaje si debe pagar
impuestos (si el sueldo supera a 3000)
Solución
Retornar
Listado completo de tutoriales
27 Clase String
La clase String está orientada a manejar cadenas de caracteres. Hasta este momento
hemos utilizado algunos métodos de la clase String (equals, compareTo)
Métodos
Retorna un caracter del String, llega al método la posición del caracter a extraer.
int length()
String toUpperCase()
String toLowerCase()
Problema 1:
Confeccionar una clase que solicite el ingreso de dos String y luego emplee los
métodos más comunes de la clase String.
Programa:
import java.util.Scanner;
public class Cadena1 {
public static void main(String[] ar) {
Scanner teclado=new Scanner(System.in);
String cad1;
String cad2;
System.out.print("Ingrese la primer cadena:");
cad1=teclado.nextLine();
System.out.print("Ingrese la segunda cadena:");
cad2=teclado.nextLine();
if (cad1.equals(cad2)==true) {
System.out.println(cad1+" es exactamente igual a "+cad2);
} else {
System.out.println(cad1+" no es exactamente igual a "+cad2);
}
if (cad1.equalsIgnoreCase(cad2)==true) {
System.out.println(cad1+" es igual a "+cad2+" sin tener en
cuenta mayúsculas/minúsculas");
} else {
System.out.println(cad1+" no es igual a "+cad2+" sin tener en
cuenta mayúsculas/minúsculas");
}
if (cad1.compareTo(cad2)==0) {
System.out.println(cad1+" es exactamente igual a "+cad2);
} else {
if (cad1.compareTo(cad2)>0) {
System.out.println(cad1+ " es mayor alfabéticamente que
"+cad2);
} else {
System.out.println(cad2+ " es mayor alfabéticamente que
"+cad1);
}
}
char carac1=cad1.charAt(0);
System.out.println("El primer caracter de "+cad1+" es "+carac1);
int largo=cad1.length();
System.out.println("El largo del String "+cad1+" es "+largo);
String cad3=cad1.substring(0,3);
System.out.println("Los primeros tres caracteres de "+cad1+" son
"+cad3);
int posi=cad1.indexOf(cad2);
if (posi==-1) {
System.out.println(cad2+" no está contenido en "+cad1);
} else {
System.out.println(cad2+" está contenido en "+cad1+" a partir
de la posición "+posi);
}
System.out.println(cad1+ " convertido a mayúsculas es
"+cad1.toUpperCase());
System.out.println(cad1+ " convertido a minúsculas es
"+cad1.toLowerCase());
}
}
Para cargar los dos String utilizamos en este caso el método nextLine para permitir
ingresar espacios en blanco:
Problemas propuestos
1. Realizar una clase, que permita cargar una dirección de mail en el constructor,
luego en otro método mostrar un mensaje si contiene el caracter '@'.
3. Desarrollar un programa que solicite la carga de una clave. La clase debe tener
dos métodos uno para la carga y otro que muestre si la clave es la correcta (la
clave a comparar es "123abc")
4. Confeccionar un programa que permita cargar los nombres de 5 personas y sus
mail, luego implementar los siguientes métodos:
a) Mostrar por pantalla los datos.
b) Consulta del mail ingresando su nombre.
c) Mostrar los mail que no tienen el carácter @.
5. Codifique un programa que permita cargar una oración por teclado, luego mostrar
cada palabra ingresada en una línea distinta.
La
mañana
está
fría.
Solución
Retornar
Listado completo de tutoriales
28 Colaboración de clases
Problema 1:
Cliente
atributos
nombre
monto
métodos
constructor
depositar
extraer
retornarMonto
Banco
atributos
3 Cliente (3 objetos de la clase Cliente)
1 Scanner (Para poder hacer la entrada de datos por teclado)
métodos
constructor
operar
depositosTotales
Creamos un proyecto en Eclipse llamado: Proyecto1 y dentro del proyecto creamos dos
clases llamadas: Cliente y Banco.
Programa:
public Banco() {
cliente1=new Cliente("Juan");
cliente2=new Cliente("Ana");
cliente3=new Cliente("Pedro");
}
Los métodos depositar y extraer actualizan el atributo monto con el dinero que llega
como parámetro (para simplificar el problema no hemos validado que cuando se extrae
dinero el atributo monto quede con un valor negativo):
Por último el método imprimir muestra nombre y el monto de dinero del cliente:
Como podemos observar la clase Cliente no tiene función main. Entonces donde
definimos objetos de la clase Cliente?
La respuesta a esta pregunta es que en la clase Banco definimos tres objetos de la
clase Cliente.
Veamos ahora la clase Banco que requiere la colaboración de la clase Cliente.
Primero definimos tres atributos de tipo Cliente:
En le constructor creamos los tres objetos (cada vez que creamos un objeto de la clase
Cliente debemos pasar a su constructor el nombre del cliente, recordemos que su
monto de depósito se inicializa con cero):
public Banco() {
cliente1=new Cliente("Juan");
cliente2=new Cliente("Ana");
cliente3=new Cliente("Pedro");
}
El método operar del banco (llamamos a los métodos depositar y extraer de los
clientes):
Por último en la main definimos un objeto de la clase Banco (la clase Banco es la clase
principal en nuestro problema):
Problema 2:
Plantear un programa que permita jugar a los dados. Las reglas de juego son: se tiran
tres dados si los tres salen con el mismo valor mostrar un mensaje que "gano", sino
"perdió".
Dado
atributos
valor
métodos
tirar
imprimir
retornarValor
JuegoDeDados
atributos
3 Dado (3 objetos de la clase Dado)
métodos
constructor
jugar
Creamos un proyecto en Eclipse llamado: Proyecto2 y dentro del proyecto creamos dos
clases llamadas: Dado y JuegoDeDados.
Programa:
public JuegoDeDados() {
dado1=new Dado();
dado2=new Dado();
dado3=new Dado();
}
La clase dado define el atributo "valor" donde almacenamos un valor aleatorio que
representa el número que sale al tirarlo.
El método tirar almacena el valor aleatorio (para generar un valor aleatorio utilizamos el
método random de la clase Math, el mismo genera un valor real comprendido entre 0 y
1, pero nunca 0 o 1. Puede ser un valor tan pequeño como 0.0001 o tan grando como
0.9999. Luego este valor generado multiplicado por 6 y antecediendo (int) obtenemos
la parte entera de dicho producto):
Como vemos le sumamos uno ya que el producto del valor aleatorio con seis puede
generar números enteros entre 0 y 5.
El método imprimir de la clase Dado muestra por pantalla el valor del dado:
public void imprimir() {
System.out.println("El valor del dado es:"+valor);
}
Por último el método que retorna el valor del dado (se utiliza en la otra clase para ver si
los tres dados generaron el mismo valor):
La clase JuegoDeDatos define tres atributos de la clase Dado (con esto decimos que la
clase Dado colabora con la clase JuegoDeDados):
public JuegoDeDados() {
dado1=new Dado();
dado2=new Dado();
dado3=new Dado();
}
En el método jugar llamamos al método tirar de cada dado, pedimos que se imprima el
valor generado y finalmente procedemos a verificar si se ganó o no:
En la main creamos solo un objeto de la clase principal (en este caso la clase principal
es el JuegoDeDados):
Problemas propuestos
1. Plantear una clase Club y otra clase Socio.
La clase Socio debe tener los siguientes atributos privados: nombre y la
antigüedad en el club (en años). En el constructor pedir la carga del nombre y su
antigüedad. La clase Club debe tener como atributos 3 objetos de la clase Socio.
Definir una responsabilidad para imprimir el nombre del socio con mayor
antigüedad en el club.
Solución
Retornar
Listado completo de tutoriales
29 Herencia
Vimos en el concepto anterior que dos clases pueden estar relacionadas por la
colaboración. Ahora veremos otro tipo de relaciones entre clases que es la Herencia.
clase padre
Clase de la que desciende o deriva una clase. Las clases hijas (descendientes)
heredan (incorporan) automáticamente los atributos y métodos de la la clase padre.
Subclase
Vehiculo
FordK Renault 9
Siempre hacia abajo en la jerarquía hay una especialización (las subclases añaden
nuevos atributos y métodos.
Software
DeAplicacion De
ProcesadorTexto PlanillaDeCalculo Si
Si tenemos una ClaseA y otra ClaseB y notamos que entre ellas existe una relacion de
tipo "... tiene un...", no debe implementarse herencia sino declarar en la clase ClaseA
un atributo de la clase ClaseB.
Por ejemplo: tenemos una clase Auto, una clase Rueda y una clase Volante. Vemos
que la relación entre ellas es: Auto "...tiene 4..." Rueda, Volante "...es parte de..." Auto;
pero la clase Auto no debe derivar de Rueda ni Volante de Auto porque la relación no
es de tiposubtipo sino de colaboración. Debemos declarar en la clase Auto 4 atributos
de tipo Rueda y 1 de tipo Volante.
Luego si vemos que dos clase responden a la pregunta ClaseA "..es un.." ClaseB es
posible que haya una relación de herencia.
Por ejemplo:
Problema 1:
Operacion
Suma Resta
Solamente el método operar es distinto para las clases Suma y Resta (esto hace que no lo
podamos disponer en la clase Operacion), luego los métodos cargar1, cargar2 y
mostrarResultado son idénticos a las dos clases, esto hace que podamos disponerlos en la
clase Operacion. Lo mismo los atributos valor1, valor2 y resultado se definirán en la clase
padre Operacion.
Crear un proyecto y luego crear cuatro clases llamadas: Operacion, Suma, Resta y
Prueba
Programa:
import java.util.Scanner;
public class Operacion {
protected Scanner teclado;
protected int valor1;
protected int valor2;
protected int resultado;
public Operacion() {
teclado=new Scanner(System.in);
}
import java.util.Scanner;
public class Operacion {
protected Scanner teclado;
protected int valor1;
protected int valor2;
protected int resultado;
Ya veremos que definimos los atributos con este nuevo modificador de acceso
(protected) para que la subclase tenga acceso a dichos atributos. Si los definimos
private las subclases no pueden acceder a dichos atributos.
public Operacion() {
teclado=new Scanner(System.in);
}
Ahora veamos como es la sintaxis para indicar que una clase hereda de otra:
void operar() {
resultado=valor1+valor2;
}
El método operar puede acceder a los atributos heredados (siempre y cuando los
mismos se declaren protected, en caso que sean private si bien lo hereda de la clase
padre solo los pueden modificar métodos de dicha clase padre.
Ahora podemos decir que la clase Suma tiene cinco métodos (cuatro heredados y uno
propio) y 3 atributos (todos heredados)
resta1.cargar1();
resta1.cargar2();
resta1.operar();
System.out.print("El resultado de la resta es:");
resta1.mostrarResultado();
}
}
Podemos llamar tanto al método propio de la clase Suma "operar()" como a los
métodos heredados. Quien utilice la clase Suma solo debe conocer que métodos
públicos tiene (independientemente que pertenezcan a la clase Suma o a una clase
superior)
Problemas propuestos
1. Confeccionar una clase Persona que tenga como atributos el nombre y la edad.
Definir como responsabilidades un método que cargue los datos personales y otro
que los imprima.
Plantear una segunda clase Empleado que herede de la clase Persona. Añadir un
atributo sueldo y los métodos de cargar el sueldo e imprimir su sueldo.
Definir un objeto de la clase Persona y llamar a sus métodos. También crear un
objeto de la clase Empleado y llamar a sus métodos.
Solución
Retornar
Listado completo de tutoriales
30 Interfaces visuales
(componentes Swing)
Hasta ahora hemos resuelto todos los algoritmos haciendo las salidas a través de una
consola en modo texto. La realidad que es muy común la necesidad de hacer la
entrada y salida de datos mediante una interfaz más amigables con el usuario.
Problema 1:
Programa:
import javax.swing.*;
public class Formulario extends JFrame{
private JLabel label1;
public Formulario() {
setLayout(null);
label1=new JLabel("Hola Mundo.");
label1.setBounds(10,20,200,30);
add(label1);
}
Hasta ahora habíamos utilizado la clase Scanner para hacer la entrada de datos por
teclado. Dicha clase debemos importarla en nuestro programa con la sintaxis:
import java.util.Scanner;
Otra sintaxis para importarla es:
import java.util.*;
Si disponemos un * indicamos que importe todas las clases del paquete java.util.
Ahora bien las componentes Swing hay que importarlas del paquete javax.swing.
Cuando debemos importar varias componentes de un paquete es más conveniente
utilizar el asterisco que indicar cada clase a importar:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.*;
La clase JFrame encapsula el concepto de una ventana. Luego para implementar una
aplicación que muestre una ventana debemos plantear una clase que herede de la
clase JFrame:
Con la sintaxis anterior estamos indicando que que la clase Formulario hereda todos
los métodos y propiedades de la clase JFrame.
public Formulario() {
setLayout(null);
Luego tenemos que crear el objeto de la clase JLabel y pasarle como parámetro al
constructor el texto a mostrar:
Cuando ejecutamos nuestro proyecto tenemos como resultado una ventana similar a
esta:
Retornar
Listado completo de tutoriales
31 Swing JFrame
La componente básica que requerimos cada vez que implementamos una interfaz
visual con la libraría Swing es la clase JFrame. Esta clase encapsula una Ventana
clásica de cualquier sistema operativo con entorno gráfico (Windows, OS X, Linux etc.)
import javax.swing.*;
import javax.swing.JFrame;
public class Formulario {
public static void main(String[] ar) {
JFrame f=new JFrame();
f.setBounds(10,10,300,200);
f.setVisible(true);
}
}
import javax.swing.JFrame;
Pero esta forma de trabajar con la clase JFrame es de poca utilidad ya que rara vez
necesitemos implementar una aplicación que muestre una ventana vacía.
Lo más correcto es plantear una clase que herede de la clase JFrame y extienda sus
responsabilidades agregando botones, etiquetas, editores de línea etc.
Entonces la estructura básica que emplearemos para crear una interfaz visual será:
Programa:
import javax.swing.*;
public class Formulario extends JFrame{
public Formulario() {
setLayout(null);
}
import javax.swing.*;
public Formulario() {
setLayout(null);
}
El método setBounds ubica el JFrame (la ventana) en la columna 10, fila 20 con un
ancho de 400 píxeles y un alto de 300.
Debemos llamar al método setVisible y pasarle el valor true para que se haga visible la
ventana.
Problemas propuestos
1. Crear una ventana de 1024 píxeles por 800 píxeles. Luego no permitir que el
operador modifique el tamaño de la ventana. Sabiendo que hacemos visible al
JFrame llamando la método setVisible pasando el valor true, existe otro método
llamado setResizable que también requiere como parámetro un valor true o false.
Solución
Retornar
Listado completo de tutoriales
32 Swing JLabel
Problema 1:
Programa:
import javax.swing.*;
public class Formulario extends JFrame {
private JLabel label1,label2;
public Formulario() {
setLayout(null);
label1=new JLabel("Sistema de Facturación.");
label1.setBounds(10,20,300,30);
add(label1);
label2=new JLabel("Vesion 1.0");
label2.setBounds(10,100,100,30);
add(label2);
}
import javax.swing.*;
public Formulario() {
setLayout(null);
label1=new JLabel("Sistema de Facturación.");
label1.setBounds(10,20,300,30);
add(label1);
label2=new JLabel("Vesion 1.0");
label2.setBounds(10,100,100,30);
add(label2);
}
Problemas propuestos
1. Crear tres objetos de la clase JLabel, ubicarlos uno debajo de otro y mostrar
nombres de colores.
Solución
Retornar
Listado completo de tutoriales
33 Swing JButton
El tercer control visual de uso muy común es el que provee la clase JButton. Este
control visual muestra un botón.
Ahora veremos la captura de eventos con los controles visuales. Uno de los eventos
más comunes es cuando hacemos clic sobre un botón.
Java implementa el concepto de interfaces para poder llamar a métodos de una clase
existente a una clase desarrollada por nosotros.
Problema 1:
Programa:
import javax.swing.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener {
JButton boton1;
public Formulario() {
setLayout(null);
boton1=new JButton("Finalizar");
boton1.setBounds(300,250,100,30);
add(boton1);
boton1.addActionListener(this);
}
La mecánica para atrapar el clic del objeto de la clase JButton se hace mediante la
implementación de una interface. Una interface es un protocolo que permite la
comunicación entre dos clases. Una interface contiene uno o más cabecera de
métodos, pero no su implementación. Por ejemplo la interface ActionListener tiene la
siguiente estructura:
interface ActionListener {
public void actionPerformed(ActionEvent e) {
}
Para indicar que una clase implementará una interface lo hacemos en la declaración de
la clase con la sintaxis:
Con esto estamos diciendo que nuestra clase implementa la interface ActionListener,
luego estamos obligados a codificar el método actionPerformed.
JButton boton1;
En el constructor creamos el objeto de la clase JButton y mediante la llamada del
método addActionListener le pasamos la referencia del objeto de la clase JButton
utilizando la palabra clave this (this almacena la dirección de memoria donde se
almacena el objeto de la clase JFrame, luego mediante dicha dirección podemos llamar
al método actionPerformed):
public Formulario() {
setLayout(null);
boton1=new JButton("Finalizar");
boton1.setBounds(300,250,100,30);
add(boton1);
boton1.addActionListener(this);
}
El método actionPerformed se ejecutará cada vez que hagamos clic sobre el objeto de
la clase JButton.
import java.awt.event.*;
Es decir que cada vez que se presiona el botón desde la clase JButton se llama al
método actionPerformed y recibe como parámetro un objeto de la clase ActionEvent.
Problema 2:
Confeccionar una ventana que contenga tres objetos de la clase JButton con las
etiquetas "1", "2" y "3". Al presionarse cambiar el título del JFrame indicando cuál botón
se presionó.
Programa:
import javax.swing.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JButton boton1,boton2,boton3;
public Formulario() {
setLayout(null);
boton1=new JButton("1");
boton1.setBounds(10,100,90,30);
add(boton1);
boton1.addActionListener(this);
boton2=new JButton("2");
boton2.setBounds(110,100,90,30);
add(boton2);
boton2.addActionListener(this);
boton3=new JButton("3");
boton3.setBounds(210,100,90,30);
add(boton3);
boton3.addActionListener(this);
}
En el constructor creamos los tres objetos de la clase JButton y los ubicamos dentro
del control JFrame (también llamamos al método addActionListener para enviarle la
dirección del objeto de la clase Formulario):
public Formulario() {
setLayout(null);
boton1=new JButton("1");
boton1.setBounds(10,100,90,30);
add(boton1);
boton1.addActionListener(this);
boton2=new JButton("2");
boton2.setBounds(110,100,90,30);
add(boton2);
boton2.addActionListener(this);
boton3=new JButton("3");
boton3.setBounds(210,100,90,30);
add(boton3);
boton3.addActionListener(this);
}
Problemas propuestos
1. Disponer dos objetos de la clase JButton con las etiquetas: "varón" y "mujer", al
presionarse mostrar en la barra de títulos del JFrame la etiqueta del botón
presionado.
Solución
Retornar
Listado completo de tutoriales
34 Swing JTextField
Así como podríamos decir que el control JLabel remplaza a la salida estándar
System.out.print, el control JTextField cumple la función de la clase Scanner para la
entrada de datos.
Problema 1:
Programa:
import javax.swing.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JTextField textfield1;
private JLabel label1;
private JButton boton1;
public Formulario() {
setLayout(null);
label1=new JLabel("Usuario:");
label1.setBounds(10,10,100,30);
add(label1);
textfield1=new JTextField();
textfield1.setBounds(120,10,150,20);
add(textfield1);
boton1=new JButton("Aceptar");
boton1.setBounds(10,80,100,30);
add(boton1);
boton1.addActionListener(this);
}
public Formulario() {
setLayout(null);
label1=new JLabel("Usuario:");
label1.setBounds(10,10,100,30);
add(label1);
textfield1=new JTextField();
textfield1.setBounds(120,10,150,20);
add(textfield1);
boton1=new JButton("Aceptar");
boton1.setBounds(10,80,100,30);
add(boton1);
boton1.addActionListener(this);
}
Problema 2:
Programa:
import javax.swing.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JTextField textfield1,textfield2;
private JButton boton1;
public Formulario() {
setLayout(null);
textfield1=new JTextField();
textfield1.setBounds(10,10,100,30);
add(textfield1);
textfield2=new JTextField();
textfield2.setBounds(10,50,100,30);
add(textfield2);
boton1=new JButton("Sumar");
boton1.setBounds(10,90,100,30);
add(boton1);
boton1.addActionListener(this);
}
String cad1=textfield1.getText();
String cad2=textfield2.getText();
int x1=Integer.parseInt(cad1);
int x2=Integer.parseInt(cad2);
Una vez que tenemos los dos valores en formato numérico procedemos a sumarlos y
almacenar el resultado en otra variable auxiliar:
int suma=x1+x2;
Ahora tenemos que mostrar el valor almacenado en suma en la barra de títulos del
control JFrame, pero como el método setTitle requiere un String como parámetro
debemos convertirlo a tipo String:
String total=String.valueOf(suma);
setTitle(total);
De String a int:
int x1=Integer.parseInt(cad1);
De int a String:
String total=String.valueOf(suma);
Problemas propuestos
1. Ingresar el nombre de usuario y clave en controles de tipo JTextField. Si se ingresa
las cadena (usuario: juan, clave=abc123) luego mostrar en el título del JFrame el
mensaje "Correcto" en caso contrario mostrar el mensaje "Incorrecto".
Solución
Retornar
Listado completo de tutoriales
35 Swing JTextArea
El control de tipo JTextArea permite ingresar múltiples líneas, a diferencia del control de
tipo JTextField.
Problema 1:
Programa:
import javax.swing.*;
public class Formulario extends JFrame{
private JTextField textfield1;
private JTextArea textarea1;
public Formulario() {
setLayout(null);
textfield1=new JTextField();
textfield1.setBounds(10,10,200,30);
add(textfield1);
textarea1=new JTextArea();
textarea1.setBounds(10,50,400,300);
add(textarea1);
}
textarea1=new JTextArea();
textarea1.setBounds(10,50,400,300);
add(textarea1);
El inconveniente que tiene este control es que si ingresamos más texto que el que
puede visualizar no aparecen las barras de scroll y no podemos ver los caracteres
tipeados.
import javax.swing.*;
public class Formulario extends JFrame{
private JTextField textfield1;
private JScrollPane scrollpane1;
private JTextArea textarea1;
public Formulario() {
setLayout(null);
textfield1=new JTextField();
textfield1.setBounds(10,10,200,30);
add(textfield1);
textarea1=new JTextArea();
scrollpane1=new JScrollPane(textarea1);
scrollpane1.setBounds(10,50,400,300);
add(scrollpane1);
}
textarea1=new JTextArea();
scrollpane1=new JScrollPane(textarea1);
scrollpane1.setBounds(10,50,400,300);
add(scrollpane1);
Problema 2:
Confeccionar un programa que permita ingresar en un control de tipo JTextArea una
carta. Luego al presionar un botón mostrar un mensaje si la carta contiene el String
"argentina".
Programa:
import javax.swing.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JScrollPane scrollpane1;
private JTextArea textarea1;
private JButton boton1;
public Formulario() {
setLayout(null);
textarea1=new JTextArea();
scrollpane1=new JScrollPane(textarea1);
scrollpane1.setBounds(10,10,300,200);
add(scrollpane1);
boton1=new JButton("Verificar");
boton1.setBounds(10,260,100,30);
add(boton1);
boton1.addActionListener(this);
}
String texto=textarea1.getText();
if (texto.indexOf("argentina")!=-1) {
setTitle("Si contiene el texto \"argentina\"");
} else {
setTitle("No contiene el texto \"argentina\"");
}
Problemas propuestos
1. Disponer dos controles de tipo JTextArea, luego al presionar un botón verificar si
tienen exactamente el mismo contenido.
Solución
Retornar
Listado completo de tutoriales
36 Swing JComboBox
Para inicializar los String que contendrá el JComboBox debemos llamar al método
addItem tantas veces como elementos queremos cargar.
Un evento muy útil con este control es cuando el operador selecciona un Item de la
lista. Para capturar la selección de un item debemos implementar la interface
ItemListener que contiene un método llamada itemStateChanged.
Problema 1:
Programa:
import javax.swing.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ItemListener{
private JComboBox combo1;
public Formulario() {
setLayout(null);
combo1=new JComboBox();
combo1.setBounds(10,10,80,20);
add(combo1);
combo1.addItem("rojo");
combo1.addItem("vede");
combo1.addItem("azul");
combo1.addItem("amarillo");
combo1.addItem("negro");
combo1.addItemListener(this);
}
combo1=new JComboBox();
Posicionamos el control:
combo1.setBounds(10,10,80,20);
add(combo1);
combo1.addItem("rojo");
combo1.addItem("vede");
combo1.addItem("azul");
combo1.addItem("amarillo");
combo1.addItem("negro");
Asociamos la clase que capturará el evento de cambio de item (con this indicamos que
esta misma clase capturará el evento):
combo1.addItemListener(this);
String seleccionado=(String)combo1.getSelectedItem();
Problema 2:
Disponer tres controles de tipo JComboBox con valores entre 0 y 255 (cada uno
representa la cantidad de rojo, verde y azul). Luego al presionar un botón pintar el
mismo con el color que se genera combinando los valores de los JComboBox.
Programa:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JLabel label1,label2,label3;
private JComboBox combo1,combo2,combo3;
private JButton boton1;
public Formulario() {
setLayout(null);
label1=new JLabel("Rojo:");
label1.setBounds(10,10,100,30);
add(label1);
combo1=new JComboBox();
combo1.setBounds(120,10,50,30);
for(int f=0;f<=255;f++) {
combo1.addItem(String.valueOf(f));
}
add(combo1);
label2=new JLabel("Verde:");
label2.setBounds(10,50,100,30);
add(label2);
combo2=new JComboBox();
combo2.setBounds(120,50,50,30);
for(int f=0;f<=255;f++) {
combo2.addItem(String.valueOf(f));
}
add(combo2);
label3=new JLabel("Azul:");
label3.setBounds(10,90,100,30);
add(label3);
combo3=new JComboBox();
combo3.setBounds(120,90,50,30);
for(int f=0;f<=255;f++) {
combo3.addItem(String.valueOf(f));
}
add(combo3);
boton1=new JButton("Fijar Color");
boton1.setBounds(10,130,100,30);
add(boton1);
boton1.addActionListener(this);
}
import java.awt.*;
label1=new JLabel("Rojo:");
label1.setBounds(10,10,100,30);
add(label1);
combo1=new JComboBox();
combo1.setBounds(120,10,50,30);
Para añadir los 256 elementos del JComboBox disponemos un for y previa a llamar al
método addItem convertimos el entero a String:
for(int f=0;f<=255;f++) {
combo1.addItem(String.valueOf(f));
}
add(combo1);
int rojo=Integer.parseInt(cad1);
int verde=Integer.parseInt(cad2);
int azul=Integer.parseInt(cad3);
Para cambiar el color de fondo del control JButton debemos llamar al método
setBackground y pasarle el objeto de la clase Color:
boton1.setBackground(color1);
Problemas propuestos
1. Solicitar el ingreso del nombre de una persona y seleccionar de un control
JComboBox un país. Al presionar un botón mostrar en la barra del título del
JFrame el nombre ingresado y el país seleccionado.
Solución
Retornar
Listado completo de tutoriales
37 Swing JMenuBar, JMenu,
JMenuItem
Problema 1:
Programa:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JMenuBar mb;
private JMenu menu1;
private JMenuItem mi1,mi2,mi3;
public Formulario() {
setLayout(null);
mb=new JMenuBar();
setJMenuBar(mb);
menu1=new JMenu("Opciones");
mb.add(menu1);
mi1=new JMenuItem("Rojo");
mi1.addActionListener(this);
menu1.add(mi1);
mi2=new JMenuItem("Verde");
mi2.addActionListener(this);
menu1.add(mi2);
mi3=new JMenuItem("Azul");
mi3.addActionListener(this);
menu1.add(mi3);
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
Definimos un objeto de la clase JMenu (esta clase tiene por objeto desplegar un
conjunto de objetos de tipo JMenuItem u otros objetos de tipo JMenu:
Definimos tres objetos de la clase JMenuItem (estos son los que disparan eventos
cuando el operador los selecciona:
mb=new JMenuBar();
setJMenuBar(mb);
menu1=new JMenu("Opciones");
mb.add(menu1);
Ahora comenzamos a crear los objetos de la clase JMenuItem y los añadimos al objeto
de la clase JMenu (también mediante la llamada al método addActionListener
indicamos al JMenuItem que objeto procesará el clic):
mi1=new JMenuItem("Rojo");
mi1.addActionListener(this);
menu1.add(mi1);
mi2=new JMenuItem("Verde");
mi2.addActionListener(this);
menu1.add(mi2);
mi3=new JMenuItem("Azul");
mi3.addActionListener(this);
menu1.add(mi3);
Luego mediante if verificamos cual de los tres JMenuItem fue seleccionado y a partir de
esto llamamos al método setBackground del objeto de la clase Container):
if (e.getSource()==mi1) {
f.setBackground(new Color(255,0,0));
}
if (e.getSource()==mi2) {
f.setBackground(new Color(0,255,0));
}
if (e.getSource()==mi3) {
f.setBackground(new Color(0,0,255));
}
}
Problema 2:
Programa:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener{
private JMenuBar mb;
private JMenu menu1,menu2,menu3;
private JMenuItem mi1,mi2,mi3,mi4;
public Formulario() {
setLayout(null);
mb=new JMenuBar();
setJMenuBar(mb);
menu1=new JMenu("Opciones");
mb.add(menu1);
menu2=new JMenu("Tamaño de la ventana");
menu1.add(menu2);
menu3=new JMenu("Color de fondo");
menu1.add(menu3);
mi1=new JMenuItem("640*480");
menu2.add(mi1);
mi1.addActionListener(this);
mi2=new JMenuItem("1024*768");
menu2.add(mi2);
mi2.addActionListener(this);
mi3=new JMenuItem("Rojo");
menu3.add(mi3);
mi3.addActionListener(this);
mi4=new JMenuItem("Verde");
menu3.add(mi4);
mi4.addActionListener(this);
}
Es importante notar el orden de creación de los objetos y como los relacionamos unos
con otros.
Primero creamos el JMenuBar y lo asociamos con el JFrame:
mb=new JMenuBar();
setJMenuBar(mb);
menu1=new JMenu("Opciones");
mb.add(menu1);
Finalmente comenzamos a crear los objetos de la clase JMenuItem y los dos primeros
los asociamos con el segundo JMenu:
mi1=new JMenuItem("640*480");
menu2.add(mi1);
mi1.addActionListener(this);
mi2=new JMenuItem("1024*768");
menu2.add(mi2);
mi2.addActionListener(this);
También hacemos lo mismo con los otros dos objetos de tipo JMenuItem pero ahora los
asociamos con el tercer JMenu:
mi3=new JMenuItem("Rojo");
menu3.add(mi3);
mi3.addActionListener(this);
mi4=new JMenuItem("Verde");
menu3.add(mi4);
mi4.addActionListener(this);
if (e.getSource()==mi2) {
setSize(1024,768);
}
if (e.getSource()==mi3) {
getContentPane().setBackground(new Color(255,0,0));
}
if (e.getSource()==mi4) {
getContentPane().setBackground(new Color(0,255,0));
}
Problemas propuestos
1. Mediante dos controles de tipo JTextField permitir el ingreso de dos números.
Crear un menú que contenga una opción que redimensione el JFrame con los
valores ingresados por teclado. Finalmente disponer otra opción que finalice el
programa (Finalizamos un programa java llamando al método exit de la clase
System: System.exit(0))
Solución
Retornar
Listado completo de tutoriales
38 Swing JCheckBox
Problema 1:
Programa:
import javax.swing.*;
import javax.swing.event.*;
public class Formulario extends JFrame implements ChangeListener{
private JCheckBox check1,check2,check3;
public Formulario() {
setLayout(null);
check1=new JCheckBox("Inglés");
check1.setBounds(10,10,150,30);
check1.addChangeListener(this);
add(check1);
check2=new JCheckBox("Francés");
check2.setBounds(10,50,150,30);
check2.addChangeListener(this);
add(check2);
check3=new JCheckBox("Alemán");
check3.setBounds(10,90,150,30);
check3.addChangeListener(this);
add(check3);
}
Lo primero y más importante que tenemos que notar que para capturar el cambio de
estado del JCheckBox hay que implementar la interface ChangeListener que se
encuentra en el paquete:
import javax.swing.event.*;
y no en el paquete:
import java.awt.event.*
check1=new JCheckBox("Inglés");
check1.setBounds(10,10,150,30);
check1.addChangeListener(this);
add(check1);
String cad="";
if (check1.isSelected()==true) {
cad=cad+"Inglés-";
}
if (check2.isSelected()==true) {
cad=cad+"Francés-";
}
if (check3.isSelected()==true) {
cad=cad+"Alemán-";
}
setTitle(cad);
Problema 2:
Disponer un control JLabel que muestre el siguiente mensaje: "Esta de acuerdo con las
normas del servicio?", luego un JCheckBox y finalmente un objeto de tipo JButton
desactivo. Cuando se tilde el JCheckBox debemos activar el botón.
Programa:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
public class Formulario extends JFrame implements ActionListener,
ChangeListener{
private JLabel label1;
private JCheckBox check1;
private JButton boton1;
public Formulario() {
setLayout(null);
label1=new JLabel("Esta de acuerdo con las normas del servicio?");
label1.setBounds(10,10,400,30);
add(label1);
check1=new JCheckBox("Acepto");
check1.setBounds(10,50,100,30);
check1.addChangeListener(this);
add(check1);
boton1=new JButton("Continuar");
boton1.setBounds(10,100,100,30);
add(boton1);
boton1.addActionListener(this);
boton1.setEnabled(false);
}
Importamos los paquetes donde se encuentran las interfaces para captura de eventos
de objetos de tipo JButton y JCheckBox:
import javax.swing.event.*;
import java.awt.event.*;
También importamos el paquete donde están definidas las clase JFrame, JButton y
JCheckBox:
import javax.swing.*;
check1=new JCheckBox("Acepto");
check1.setBounds(10,50,100,30);
check1.addChangeListener(this);
add(check1);
boton1=new JButton("Continuar");
boton1.setBounds(10,100,100,30);
add(boton1);
boton1.addActionListener(this);
boton1.setEnabled(false);
Problemas propuestos
1. Disponer tres objetos de la clase JCheckBox con nombres de navegadores web.
Cuando se presione un botón mostrar en el título del JFrame los programas
seleccionados.
Solución
Retornar
Listado completo de tutoriales
39 Swing JRadioButton
Problema 1:
Programa:
import javax.swing.*;
import javax.swing.event.*;
public class Formulario extends JFrame implements ChangeListener{
private JRadioButton radio1,radio2,radio3;
private ButtonGroup bg;
public Formulario() {
setLayout(null);
bg=new ButtonGroup();
radio1=new JRadioButton("640*480");
radio1.setBounds(10,20,100,30);
radio1.addChangeListener(this);
add(radio1);
bg.add(radio1);
radio2=new JRadioButton("800*600");
radio2.setBounds(10,70,100,30);
radio2.addChangeListener(this);
add(radio2);
bg.add(radio2);
radio3=new JRadioButton("1024*768");
radio3.setBounds(10,120,100,30);
radio3.addChangeListener(this);
add(radio3);
bg.add(radio3);
}
Importamos los dos paquetes donde están definidas las clases e interfaces para la
captura de eventos:
import javax.swing.*;
import javax.swing.event.*;
bg=new ButtonGroup();
radio1=new JRadioButton("640*480");
radio1.setBounds(10,20,100,30);
radio1.addChangeListener(this);
add(radio1);
bg.add(radio1);
radio2=new JRadioButton("800*600");
radio2.setBounds(10,70,100,30);
radio2.addChangeListener(this);
add(radio2);
bg.add(radio2);
radio3=new JRadioButton("1024*768");
radio3.setBounds(10,120,100,30);
radio3.addChangeListener(this);
add(radio3);
bg.add(radio3);
Problemas propuestos
1. Permitir el ingreso de dos números en controles de tipo JTextField y mediante dos
controles de tipo JRadioButton permitir seleccionar si queremos sumarlos o
restarlos. Al presionar un botón mostrar en el título del JFrame el resultado de la
operación.
Solución
Retornar
Listado completo de tutoriales
40 Estructuras dinámicas
Conocemos algunas estructuras de datos como son los vectores y matrices. No son las
únicas. Hay muchas situaciones donde utilizar alguna de estas estructuras nos
proporcionará una solución muy ineficiente (cantidad de espacio que ocupa en
memoria, velocidad de acceso a la información, etc.)
Tiene que existir alguna estructura de datos que pueda hacer más eficiente la solución
del problema anterior.
Bien, todos estos problemas y muchos más podrán ser resueltos en forma eficiente
cuando conozcamos estas nuevas estructuras de datos (Listas, árboles)
Retornar
Listado completo de tutoriales
41 Estructuras dinámicas:
Listas
Una lista es un conjunto de nodos, cada uno de los cuales tiene dos campos: uno de
información y un apuntador al siguiente nodo de la lista. Además un apuntador externo
señala el primer nodo de la lista.
La información puede ser cualquier tipo de dato simple, estructura de datos o inclusive
uno o más objetos.
La dirección al siguiente nodo es un puntero.
Como decíamos, una lista es una secuencia de nodos (en este caso cuatro nodos). La
información de los nodos en este caso es un entero y siempre contiene un puntero que
guarda la dirección del siguiente nodo.
raiz es otro puntero externo a la lista que contiene la dirección del primer nodo.
Tipos de listas.
Listas genéricas.
Una lista se comporta como una pila si las inserciones y extracciones las hacemos por
un mismo lado de la lista. También se las llama listas LIFO (Last In First Out último en
entrar primero en salir)
Una lista se comporta como una cola si las inserciones las hacemos al final y las
extracciones las hacemos por el frente de la lista. También se las llama listas FIFO
(First In First Out primero en entrar primero en salir)
Una lista se comporta como genérica cuando las inserciones y extracciones se realizan
en cualquier parte de la lista.
Podemos en algún momento insertar un nodo en medio de la lista, en otro momento al
final, borrar uno del frente, borrar uno del fondo o uno interior, etc.
Retornar
Listado completo de tutoriales
42 Estructuras dinámicas:
Listas tipo Pila
Una lista se comporta como una pila si las inserciones y extracciones las hacemos por
un mismo lado de la lista. También se las llama listas LIFO (Last In First Out último en
entrar primero en salir)
Importante: Una pila al ser una lista puede almacenar en el campo de información
cualquier tipo de valor (int, char, float, vector de caracteres, un objeto, etc)
Inicialmente la PILA está vacía y decimos que el puntero raiz apunta a null (Si apunta a
null decimos que no tiene una dirección de memoria):
Luego de realizar la inserción la lista tipo pila queda de esta manera: un nodo con el
valor 10 y raiz apunta a dicho nodo. El puntero del nodo apunta a null ya que no hay
otro nodo después de este.
Ahora el primer nodo de la pila es el que almacena el valor cuatro. raiz apunta a dicho
nodo. Recordemos que raiz es el puntero externo a la lista que almacena la dirección
del primer nodo. El nodo que acabamos de insertar en el campo puntero guarda la
dirección del nodo que almacena el valor 10.
Ahora qué sucede si extraemos un nodo de la pila. ¿Cuál se extrae? Como sabemos
en una pila se extrae el último en entrar.
Problema 1:
Confeccionar una clase que administre una lista tipo pila (se debe poder insertar,
extraer e imprimir los datos de la pila)
Programa:
class Nodo {
int info;
Nodo sig;
}
public Pila () {
raiz=null;
}
class Nodo {
int info;
Nodo sig;
}
Para declarar un nodo debemos utilizar una clase. En este caso la información del
nodo (info) es un entero y siempre el nodo tendrá una referencia de tipo Nodo, que le
llamamos sig.
El puntero sig apunta al siguiente nodo o a null en caso que no exista otro nodo. Este
puntero es interno a la lista.
También definimos un puntero de tipo Nodo llamado raiz. Este puntero tiene la
dirección del primer nodo de la lista. En caso de estar vacía la lista, raiz apunta a null
(es decir no tiene dirección)
El puntero raiz es fundamental porque al tener la dirección del primer nodo de la lista
nos permite acceder a los demás nodos.
public Pila () {
raiz=null;
}
Uno de los métodos más importantes que debemos entender en una pila es el de
insertar un elemento en la pila.
Al método llega la información a insertar, en este caso en particular es un valor entero.
Nodo nuevo;
nuevo.info = x;
Por último queda enlazar el nodo que acabamos de crear al principio de la lista.
Si la lista está vacía debemos guardar en el campo sig del nodo el valor null para
indicar que no hay otro nodo después de este, y hacer que raiz apunte al nodo creado
(sabemos si una lista esta vacía si raiz almacena un null)
if (raiz==null)
{
nuevo.sig = null;
raiz = nuevo;
}
En caso que la lista no esté vacía, el puntero sig del nodo que acabamos de crear debe
apuntar al que es hasta este momento el primer nodo, es decir al nodo que apunta raiz
actualmente.
else
{
nuevo.sig = raiz;
raiz = nuevo;
}
Como primera actividad cargamos en el puntero sig del nodo apuntado por nuevo la
dirección de raiz, y posteriormente raiz apunta al nodo que acabamos de crear, que
será ahora el primero de la lista.
nuevo.sig = raiz;
Ahora tenemos:
raiz = nuevo;
La lista queda:
El método extraer:
El objetivo del método extraer es retornar la información del primer nodo y además
borrarlo de la lista.
Si la lista no está vacía guardamos en una variable local la información del primer
nodo:
raiz = raiz.sig;
el nodo que previamente estaba apuntado por raiz es eliminado automáticamente por
la máquina virtual de Java, al no tener ninguna referencia.
Retornamos la información:
return informacion;
return Integer.MAX_VALUE;
Definimos un puntero auxiliar reco y hacemos que apunte al primer nodo de la lista:
Nodo reco=raiz;
Disponemos una estructura repetitiva que se repetirá mientras reco sea distinto a null.
Dentro de la estructura repetitiva hacemos que reco avance al siguiente nodo:
while (reco!=null) {
System.out.print(reco.info+"-");
reco=reco.sig;
}
Estamos diciendo que reco almacena la dirección que tiene el puntero sig del nodo
apuntado actualmente por reco.
Gráficamente:
Al analizarse la condición:
while (reco!=null) {
reco=reco.sig;
reco=reco.sig;
Ahora sí reco apunta a null y ha llegado el final de la lista (Recordar que el último nodo
de la lista tiene almacenado en el puntero sig el valor null, con el objetivo de saber que
es el último nodo)
Para poder probar esta clase recordemos que debemos definir un objeto de la misma y
llamar a sus métodos:
Problema 2:
Agregar a la clase Pila un método que retorne la cantidad de nodos y otro que indique
si esta vacía.
Programa:
class Nodo {
int info;
Nodo sig;
}
Pila () {
raiz=null;
}
Para verificar si la pila esta vacía verificamos el contenido de la variable raiz, si tiene
null luego la lista esta vacía y por lo tanto retornamos un true:
Para probar esta clase en la main creamos un objeto de la clase Pila insertamos tres
enteros:
pila1.imprimir();
while (pila1.vacia()==false) {
System.out.println(pila1.extraer());
}
Problemas propuestos
1. Agregar un método a la clase Pila que retorne la información del primer nodo de la
Pila sin borrarlo.
Solución
Retornar
Listado completo de tutoriales
44 Estructuras dinámicas:
Listas tipo Cola
Una lista se comporta como una cola si las inserciones las hacemos al final y las
extracciones las hacemos por el frente de la lista. También se las llama listas FIFO
(First In First Out primero en entrar primero en salir)
Programa:
class Nodo {
int info;
Nodo sig;
}
Cola() {
raiz=null;
fondo=null;
}
int extraer ()
{
if (!vacia ())
{
int informacion = raiz.info;
if (raiz == fondo){
raiz = null;
fondo = null;
} else {
raiz = raiz.sig;
}
return informacion;
} else
return Integer.MAX_VALUE;
}
La declaración del nodo es igual a la clase Pila. Luego definimos dos punteros
externos:
raíz apunta al principio de la lista y fondo al final de la lista. Utilizar dos punteros tiene
como ventaja que cada vez que tengamos que insertar un nodo al final de la lista no
tengamos que recorrerla. Por supuesto que es perfectamente válido implementar una
cola con un único puntero externo a la lista.
Cola() {
raiz=null;
fondo=null;
}
El método vacía retorna true si la lista no tiene nodos y false en caso contrario:
boolean vacia (){
if (raiz == null)
return true;
else
return false;
}
En la inserción luego de crear el nodo tenemos dos posibilidades: que la cola esté
vacía, en cuyo caso los dos punteros externos a la lista deben apuntar al nodo creado,
o que haya nodos en la lista.
Nodo nuevo;
nuevo = new Nodo ();
nuevo.info = info;
nuevo.sig = null;
if (vacia ()) {
raiz = nuevo;
fondo = nuevo;
} else {
fondo.sig = nuevo;
fondo = nuevo;
}
Recordemos que definimos un puntero llamado nuevo, luego creamos el nodo con el
operador new y cargamos los dos campos, el de información con lo que llega en el
parámetro y el puntero con null ya que se insertará al final de la lista, es decir no hay
otro después de este.
Debemos enlazar el puntero sig del último nodo con el nodo recién creado:
fondo.sig = nuevo;
Y por último el puntero externo fondo debe apuntar al nodo apuntado por nuevo:
fondo = nuevo;
Con esto ya tenemos correctamente enlazados los nodos en la lista tipo cola. Recordar
que el puntero nuevo desaparece cuando se sale del método insertar, pero el nodo
creado no se pierde porque queda enlazado en la lista.
int extraer ()
{
if (!vacia ())
{
int informacion = raiz.info;
if (raiz == fondo){
raiz = null;
fondo = null;
} else {
raiz = raiz.sig;
}
return informacion;
} else
return Integer.MAX_VALUE;
}
Si la lista no está vacía guardamos en una variable local la información del primer
nodo:
Para saber si hay un solo nodo verificamos si los dos punteros raiz y fondo apuntan a
la misma dirección de memoria:
if (raiz == fondo){
Luego hacemos:
raiz = null;
fondo = null;
En caso de haber 2 o más nodos debemos avanzar el puntero raiz al siguiente nodo:
raiz = raiz.sig;
Retornar
Listado completo de tutoriales
43 Estructuras dinámicas:
Listas tipo Pila Problema de aplicación
Hasta ahora hemos visto como desarrollar los algoritmos para administrar una lista tipo
Pila, hemos visto que hay bastante complejidad en el manejo de punteros pero todo
esto acarrea ventajas en la solución de problemas que requieren una estructura de tipo
Pila.
Este práctico tiene por objetivo mostrar la importancia de las pilas en las Ciencias de la
Computación y más precisamente en la programación de software de bajo nivel.
Se debe desarrollar una clase que tenga las siguientes responsabilidades (clase
Formula):
Para la solución de este problema la clase formula tendrá un atributo de la clase Pila.
Veamos como nos puede ayudar el empleo de una pila para solucionar este problema.
Primero cargaremos la fórmula en un JTextField.
Programa:
class Nodo {
char simbolo;
Nodo sig;
}
Pila () {
raiz=null;
}
import javax.swing.*;
import java.awt.event.*;
public class Formula extends JFrame implements ActionListener {
private JTextField tf1;
private JButton boton1;
public Formula() {
setLayout(null);
tf1=new JTextField("{2*(4-5)-{3*4}-[4-5]}");
tf1.setBounds(10,10,230,30);
add(tf1);
boton1=new JButton("Verificar fórmula.");
boton1.setBounds(10,70,180,30);
add(boton1);
boton1.addActionListener(this);
}
setLayout(null);
tf1=new JTextField("{2*(4-5)-{3*4}-[4-5]}");
tf1.setBounds(10,10,230,30);
add(tf1);
boton1=new JButton("Verificar fórmula.");
boton1.setBounds(10,70,180,30);
add(boton1);
boton1.addActionListener(this);
Pila pila1;
pila1 = new Pila ();
String cadena=tf1.getText();
if (cadena.charAt(f)==')') {
if (pila1.extraer()!='(') {
return false;
}
Al finalizar el análisis de toda la cadena si la pila está vacía podemos afirmar que la
fórmula está correctamente balanceada, en caso contrario quiere decir que faltan
símbolos de cerrado y es incorrecta:
if (pila1.vacia()) {
return true;
} else {
return false;
}
Es importante entender que la clase Formula utiliza un objeto de la clase Pila para
resolver el algoritmo de verificar el balanceo de la fórmula, pero no accede
directamente a los nodos de la lista.
Retornar
Listado completo de tutoriales
45 Estructuras dinámicas:
Listas tipo Cola Problemas de aplicación
Este práctico tiene por objetivo mostrar la importancia de las colas en las Ciencias de la
Computación y más precisamente en las simulaciones.
Las simulaciones permiten analizar situaciones de la realidad sin la necesidad de
ejecutarlas realmente. Tiene el beneficio que su costo es muy inferior a hacer pruebas
en la realidad.
Programa:
class Nodo {
int info;
Nodo sig;
}
Nodo raiz,fondo;
Cola() {
raiz=null;
fondo=null;
}
int extraer ()
{
if (!vacia ())
{
int informacion = raiz.info;
if (raiz == fondo){
raiz = null;
fondo = null;
} else {
raiz = raiz.sig;
}
return informacion;
} else
return Integer.MAX_VALUE;
}
import javax.swing.*;
import java.awt.event.*;
public class Cajero extends JFrame implements ActionListener{
private JLabel l1,l2,l3;
private JButton boton1;
public Cajero() {
tL t( ll)
setLayout(null);
boton1=new JButton("Activar Simulación");
boton1.setBounds(10,10,180,30);
add(boton1);
boton1.addActionListener(this);
l1=new JLabel("Atendidos:");
l1.setBounds(10,50,300,30);
add(l1);
l2=new JLabel("En cola:");
l2.setBounds(10,90,300,30);
add(l2);
l3=new JLabel("Minuto de llegada:");
l3.setBounds(10,130,400,30);
add(l3);
}
La clase Cajero define tres objetos de la clase JLabel para mostrar los resultados de la
simulación.
int estado = 0;
int llegada = 2 + (int) (Math.random () * 2);
int salida = -1;
int cantAtendidas = 0;
Cola cola = new Cola ();
La variable estado almacena un cero si el cajero está libre y un uno cuando está
ocupado.
La variable llegada almacena en que minuto llegará el próximo cliente (debemos
generar un valor entre 2 y 3)
La variable salida almacenará en que minuto terminará el cliente de ser atendido (como
al principio el cajero está vacío inicializamos esta variable con 1.
Luego definimos un objeto de la clase Cola para poder almacenar las personas que
llegan al cajero y se lo encuentran ocupado.
Disponemos un for que se repita 600 veces (600 minutos o lo que es lo mismo 10
horas)
Dentro del for hay dos if fundamentales que verifican que sucede cuando llega una
persona o cuando una persona se retira:
if (llegada == minuto)
{
............
}
if (salida == minuto)
{
............
}
Cuando llega una persona al cajero primero verificamos si el cajero está desocupado:
if (llegada == minuto)
{
if (estado==0) {
estado=1;
salida=minuto+2+(int)(Math.random()*3);
} else {
cola.insertar(minuto);
}
llegada=minuto+2+(int)(Math.random()*2);
El otro if importante es ver que sucede cuando sale la persona del cajero:
if (salida == minuto) {
Si sale una persona del cajero cambiamos el valor de la variable estado,
incrementamos en uno el contador cantAtendidos y si la cola no está vacía extraemos
una persona, cambiamos a uno la variable estado y generamos en que minuto dejará
esta persona el cajero:
estado=0;
cantAtendidas++;
if (!cola.vacia()) {
cola.extraer();
estado=1;
salida=minuto+2+(int)(Math.random()*3);
}
}
l1.setText("Atendidos:"+String.valueOf(cantAtendidas));
l2.setText("En cola"+String.valueOf(cola.cantidad()));
l3.setText("Minuto llegada:"+String.valueOf(cola.extraer()));
Problemas propuestos
1. Un supermercado tiene tres cajas para la atención de los clientes.
Las cajeras tardan entre 7 y 11 minutos para la atención de cada cliente.
Los clientes llegan a la zona de cajas cada 2 ó 3 minutos. (Cuando el cliente
llega, si todas las cajas tienen 6 personas, el cliente se marcha del
supermercado)
Cuando el cliente llega a la zona de cajas elige la caja con una cola menor.
Solución
Retornar
Listado completo de tutoriales
46 Estructuras dinámicas:
Listas genéricas
Continuando con el tema de listas trabajaremos con las listas genéricas. Una lista se
comporta como genérica cuando las inserciones y extracciones se realizan en
cualquier parte de la lista.
Codificaremos una serie de métodos para administrar listas genéricas.
Métodos a desarrollar:
Extrae la información del nodo de la posición indicada (pos). Se debe eliminar el nodo.
int mayor()
int posMayor()
int cantidad()
Debe retornar true si la lista está ordenada de menor a mayor, false en caso contrario.
boolean ordenada()
Debe retornar true si existe la información que llega en el parámetro, false en caso
contrario.
boolean vacia()
Programa:
class Nodo {
int info;
Nodo sig;
}
public ListaGenerica () {
raiz=null;
}
Primero con un if verificamos que exista esa posición en la lista (por ejemplo si la lista
tiene 4 nodos podemos insertar hasta la posición 5, es decir uno más allá del último):
if (pos <= cantidad () + 1) {
if (pos == 1){
Si llega un 1 luego enlazamos el puntero sig del nodo que creamos con la dirección del
primer nodo de la lista (raiz apunta siempre al primer nodo de la lista) y luego
desplazamos raiz al nodo que acabamos de crear:
nuevo.sig = raiz;
raiz = nuevo;
if (pos == cantidad () + 1) {
y enlazamos el puntero sig del último nodo de la lista con la dirección del nodo que
acabamos de crear (disponemos en sig del nodo creado el valor null ya que no hay otro
nodo más adelante)
reco.sig = nuevo;
nuevo.sig = null;
Disponemos otro puntero auxiliar que apunte al nodo próximo a donde está apuntando
reco. Ahora enlazamos el puntero sig del nodo apuntado por reco con la dirección del
nodo creado y el puntero sig del nodo creado con la dirección del nodo siguiente:
if (pos == 1) {
informacion = raiz.info;
raiz = raiz.sig;
reco.sig = prox.sig;
El método borrar es muy similar al método extraer con la diferencia de que no retorna
valor:
El método intercambiar recibe dos enteros que representan las posiciones de los nodos
que queremos intercambiar sus informaciones:
Definimos un puntero auxiliar llamado reco1, lo inicializamos con la dirección del primer
nodo y mediante un for avanzamos hasta la posición almacenada en pos1:
De forma similar con un segundo puntero auxiliar avanzamos hasta la posición indicada
por pos2:
Nodo reco2 = raiz;
for (int f = 1 ; f < pos2 ; f++)
reco2 = reco2.sig;
if (!vacia ()) {
Cada vez que encontramos un nodo con información mayor que la variable may la
actualizamos con este nuevo valor y avanzamos el puntero reco para visitar el
siguiente nodo:
return may;
El método que retorna la posición del mayor es similar al anterior con la salvedad que
debemos almacenar en otro auxiliar la posición donde se almacena el mayor:
public int posMayor() {
if (!vacia ()) {
int may = raiz.info;
int x=1;
int pos=x;
Nodo reco = raiz.sig;
while (reco != null){
if (reco.info > may) {
may = reco.info;
pos=x;
}
reco = reco.sig;
x++;
}
return pos;
}
else
return Integer.MAX_VALUE;
}
El método que debe retornar si está ordenada la lista de menor a mayor es:
Lo primero que verificamos si la lista tiene más de un nodo significa que debemos
controlarla:
if (cantidad()>1) {
Disponemos dos punteros auxiliares con las direcciones del primer y segundo nodo de
la lista:
Nodo reco1=raiz;
Nodo reco2=raiz.sig;
while (reco2!=null) {
controlamos si la información del segundo nodo es menor al nodo anterior significa que
la lista no está ordenada y podemos parar el análisis retornando un false
if (reco2.info<reco1.info) {
return false;
Dentro del while avanzamos los dos punteros a sus nodos siguientes respectivamente.
reco2=reco2.sig;
reco1=reco1.sig;
Fuera del while retornamos true indicando que la lista está ordenada de menor a mayor
return true;
El método existe:
Nodo reco=raiz;
while (reco!=null) {
if (reco.info==x)
return true;
reco=reco.sig;
Fuera del while retornamos false indicando que ningún nodo coincide con el parámetro
x:
return false;
Problemas propuestos
1. Plantear una clase para administrar una lista genérica implementando los
siguientes métodos:
a) Insertar un nodo al principio de la lista.
b) Insertar un nodo al final de la lista.
c) Insertar un nodo en la segunda posición. Si la lista está vacía no se inserta
el nodo.
d) Insertar un nodo en la ante última posición.
e) Borrar el primer nodo.
f) Borrar el segundo nodo.
g) Borrar el último nodo.
h) Borrar el nodo con información mayor.
Solución
Retornar
Listado completo de tutoriales
47 Estructuras dinámicas:
Listas genéricas ordenadas
Ejemplo:
listaOrdenada.insertar(10)
listaOrdenada.insertar(5)
listaOrdenada.insertar(7)
listaOrdenada.insertar(50)
Podemos observar que si recorremos la lista podemos acceder a la información de
menor a mayor.
No se requiere un método para ordenar la lista, sino que siempre permanece ordenada,
ya que se inserta ordenada.
Programa:
class Nodo {
int info;
Nodo sig;
}
public ListaOrdenada() {
raiz=null;
}
void insertar(int x)
{
Nodo nuevo = new Nodo ();
nuevo.info = x;
if (raiz==null) {
raiz=nuevo;
} else {
if (x<raiz.info) {
nuevo.sig=raiz;
raiz=nuevo;
} else {
Nodo reco=raiz;
Nodo atras=raiz;
while (x>=reco.info && reco.sig!=null)
atras=reco;
reco=reco.sig;
}
if (x>=reco.info) {
reco.sig=nuevo;
} else {
nuevo.sig=reco;
atras.sig=nuevo;
}
}
}
}
if (raiz==null) {
raiz=nuevo;
} else {
Nodo reco=raiz;
Nodo atras=raiz;
while (x>=reco.info && reco.sig!=null) {
atras=reco;
reco=reco.sig;
}
if (x>=reco.info) {
reco.sig=nuevo;
} else {
nuevo.sig=reco;
atras.sig=nuevo;
}
Retornar
Listado completo de tutoriales
48 Estructuras dinámicas:
Listas genéricas doblemente encadenadas
A las listas vistas hasta el momento podemos recorrerlas solamente en una dirección
(Listas simplemente encadenadas). Hay problemas donde se requiere recorrer la lista
en ambas direcciones, en estos casos el empleo de listas doblemente encadenadas es
recomendable.
Como ejemplo pensemos que debemos almacenar un menú de opciones en una lista,
la opción a seleccionar puede ser la siguiente o la anterior, podemos desplazarnos en
ambas direcciones.
Observemos que una lista doblemente encadenada tiene dos punteros por cada nodo,
uno apunta al nodo siguiente y otro al nodo anterior.
Seguimos teniendo un puntero (raiz) que tiene la dirección del primer nodo.
El puntero sig del último nodo igual que las listas simplemente encadenadas apunta a
null, y el puntero ant del primer nodo apunta a null.
Se pueden plantear Listas tipo pila, cola y genéricas con enlace doble.
Hay que tener en cuenta que el requerimiento de memoria es mayor en las listas
doblemente encadenadas ya que tenemos dos punteros por nodo.
class Nodo {
int info;
Nodo sig, ant;
}
class Nodo {
int info;
Nodo ant,sig;
}
public ListaGenerica () {
raiz=null;
}
Primero con un if verificamos que exista esa posición en la lista (por ejemplo si la lista
tiene 4 nodos podemos insertar hasta la posición 5, es decir uno más allá del último):
if (pos == 1){
Si llega un 1 luego enlazamos el puntero sig del nodo que creamos con la dirección del
primer nodo de la lista (raiz apunta siempre al primer nodo de la lista)
Verificamos si raiz está apuntando actualmente a un nodo, en caso afirmativo
enlazamos el puntero ant con el nodo que acabamos de crear y luego desplazamos
raiz al nodo creado:
nuevo.sig = raiz;
if (raiz!=null)
raiz.ant=nuevo;
raiz = nuevo;
if (pos == cantidad () + 1) {
y enlazamos el puntero sig del último nodo de la lista con la dirección del nodo que
acabamos de crear (disponemos en sig del nodo creado el valor null ya que no hay otro
nodo más adelante) El puntero ant del nodo que creamos lo enlazamos con el nodo
que era último hasta este momento y está siendo apuntado por reco:
reco.sig = nuevo;
nuevo.ant=reco;
nuevo.sig = null;
Disponemos otro puntero auxiliar que apunte al nodo próximo a donde está apuntando
reco. Ahora enlazamos el puntero sig del nodo apuntado por reco con la dirección del
nodo creado y el puntero sig del nodo creado con la dirección del nodo siguiente. El
puntero ant del nodo apuntado por nuevo lo enlazamos con el nodo apuntado por raiz y
el puntero ant del nodo apuntado por siguiente lo apuntamos a nuevo (con esto
tenemos actualizados los cuatro punteros internos a la lista):
if (pos == 1) {
informacion = raiz.info;
raiz = raiz.sig;
if (raiz!=null)
raiz.ant=null;
Si el nodo a extraer no está al principio de la lista avanzamos con una estructura
repetitiva hasta el nodo anterior a extraer:
Ahora enlazamos el puntero sig del nodo apuntado por reco al nodo siguiente del nodo
apuntado por prox (es decir el nodo apuntado por prox queda fuera de la lista)
disponemos finalmente otro puntero llamado siguiente que apunte al nodo que se
encuentra una posición más adelante del nodo apuntado por prox, si dicho puntero
apunta a un nodo actualizamos el puntero ant de dicho nodo con la dirección del nodo
apuntado por reco:
reco.sig = prox.sig;
Nodo siguiente=prox.sig;
if (siguiente!=null)
siguiente.ant=reco;
informacion = prox.info;
El método borrar es muy similar al método extraer con la diferencia de que no retorna
valor:
El método intercambiar recibe dos enteros que representan las posiciones de los nodos
que queremos intercambiar sus informaciones:
Definimos un puntero auxiliar llamado reco1, lo inicializamos con la dirección del primer
nodo y mediante un for avanzamos hasta la posición almacenada en pos1:
De forma similar con un segundo puntero auxiliar avanzamos hasta la posición indicada
por pos2:
if (!vacia ()) {
Cada vez que encontramos un nodo con información mayor que la variable may la
actualizamos con este nuevo valor y avanzamos el puntero reco para visitar el
siguiente nodo:
return may;
El método que retorna la posición del mayor es similar al anterior con la salvedad que
debemos almacenar en otro auxiliar la posición donde se almacena el mayor:
El método que debe retornar si está ordenada la lista de menor a mayor es:
Lo primero que verificamos si la lista tiene más de un nodo significa que debemos
controlarla:
if (cantidad()>1) {
Disponemos dos punteros auxiliares con las direcciones del primer y segundo nodo de
la lista:
Nodo reco1=raiz;
Nodo reco2=raiz.sig;
while (reco2!=null) {
controlamos si la información del segundo nodo es menor al nodo anterior significa que
la lista no está ordenada y podemos parar el análisis retornando un false
if (reco2.info<reco1.info) {
return false;
Dentro del while avanzamos los dos punteros a sus nodos siguientes respectivamente.
reco2=reco2.sig;
reco1=reco1.sig;
Fuera del while retornamos true indicando que la lista está ordenada de menor a mayor
return true;
El método existe:
Nodo reco=raiz;
while (reco!=null) {
Fuera del while retornamos false indicando que ningún nodo coincide con el parámetro
x:
return false;
Problemas propuestos
1. Plantear una clase para administrar una lista genérica doblemente encadenada
implementando los siguientes métodos:
a) Insertar un nodo al principio de la lista.
b) Insertar un nodo al final de la lista.
c) Insertar un nodo en la segunda posición. Si la lista está vacía no se inserta
el nodo.
d) Insertar un nodo en la ante última posición.
e) Borrar el primer nodo.
f) Borrar el segundo nodo.
g) Borrar el último nodo.
h) Borrar el nodo con información mayor.
Solución
Retornar
Listado completo de tutoriales
49 Estructuras dinámicas:
Listas genéricas circulares
Observemos que el puntero sig del último nodo apunta al primer nodo. En este tipo de
listas si avanzamos raiz no perdemos la referencia al nodo anterior ya que es un
círculo.
El puntero ant del primer nodo apunta al último nodo de la lista y el puntero sig del
último nodo de la lista apunta al primero.
Programa:
class Nodo {
int info;
Nodo ant,sig;
}
Si la lista está vacía luego tanto el puntero sig y ant apuntan a si mismo ya que debe
ser circular (y raiz apunta al nodo creado):
if (raiz==null) {
nuevo.sig=nuevo;
nuevo.ant=nuevo;
raiz=nuevo;
En caso que la lista no esté vacía disponemos un puntero al final de la lista (el puntero
ant del primer nodo tiene dicha dirección):
} else {
Nodo ultimo=raiz.ant;
nuevo.sig=raiz;
nuevo.ant=ultimo;
raiz.ant=nuevo;
ultimo.sig=nuevo;
Finalmente hacemos que raiz apunte al nodo creado luego de haber hecho todos los
enlaces:
raiz=nuevo;
Para imprimir la lista ya no podemos disponer un puntero reco que apunte al primer
nodo y que se detenga cuando encuentre un nodo que el atributo sig almacene null.
if (!vacia()) {
Nodo reco=raiz;
do {
System.out.print (reco.info + "-");
reco = reco.sig;
} while (reco!=raiz);
System.out.println();
}
}
} else {
Nodo ultimo=raiz.ant;
raiz = raiz.sig;
ultimo.sig=raiz;
raiz.ant=ultimo;
}
Retornar
Listado completo de tutoriales
50 Recursividad: Conceptos
básicos
Primero debemos decir que la recursividad no es una estructura de datos, sino que es
una técnica de programación que nos permite que un bloque de instrucciones se
ejecute n veces. Remplaza en ocasiones a estructuras repetitivas.
Este concepto será de gran utilidad para el capítulo de la estructura de datos tipo árbol.
Cuando un método se llama a sí mismo, se asigna espacio en la pila para las nuevas
variables locales y parámetros.
Al volver de una llamada recursiva, se recuperan de la pila las variables locales y los
parámetros antiguos y la ejecución se reanuda en el punto de la llamada al método.
Problema 1:
Programa:
void repetir() {
repetir();
}
Problema 2:
Programa:
void imprimir(int x) {
System.out.println(x);
imprimir(x-1);
}
Problema 3:
Programa:
void imprimir(int x) {
if (x>0) {
System.out.println(x);
imprimir(x-1);
}
}
Problema 4:
Programa:
Con este ejemplo se presenta una situación donde debe analizarse línea a línea la
ejecución del programa y el porque de estos resultados.
void imprimir(int x) {
if (x>0) {
imprimir(x-1);
System.out.println(x);
}
}
Cuando x vale 0 la condición del if se valúa como falsa y sale de la función imprimir.
¿Qué línea ahora se ejecuta ?
Vuelve a la función main ? NO.
System.out.println(x);
Ahora si analicemos que valor tiene el parámetro x. Observemos la pila de llamadas del
gráfico:
Es importante tener en cuenta que siempre en una función recursiva debe haber un if
para finalizar la recursividad ( en caso contrario la función recursiva será infinita y
provocará que el programa se bloquee)
Problema 5:
Programa:
Cuando fact recibe un cero la condición del if se valúa como falsa y ejecuta el else
retornando un 1, la variable local de la llamada anterior a la función queda de la
siguiente manera:
Es importantísimo entender la liberación del espacio de las variables locales y los
parámetros en las sucesivas llamadas recursivas.
Por último la función main recibe "valor", en este caso el valor 24.
Problema 6:
Programa:
class Recursivdad {
static int [] vec = {312, 614, 88, 22, 54};
void imprimir () {
for (int f = 0 ; f < vec.length ; f++)
System.out.print (vec [f] + " ");
System.out.println("\n");
}
Hasta ahora hemos visto problemas que se pueden resolver tanto con recursividad
como con estructuras repetitivas.
Es muy importante tener en cuenta que siempre que podamos emplear un algoritmo no
recursivo será mejor (ocupa menos memoria de ram y se ejecuta más rápidamente)
Pero hay casos donde el empleo de recursividad hace mucho más sencillo el algoritmo
(tener en cuenta que no es el caso de los tres problemas vistos previamente)
Retornar
Listado completo de tutoriales
51 Recursividad: Problemas
donde conviene aplicar la recursividad
Problema 1:
Programa:
class Nodo {
int info;
Nodo sig;
}
void insertarPrimero(int x)
{
Nodo nuevo = new Nodo ();
nuevo.info = x;
nuevo.sig=raiz;
raiz=nuevo;
}
Cuando llamamos al método recursivo le enviamos raiz y el parámetro reco recibe esta
dirección. Si reco es distinto a null llamamos recursivamente al método enviándole la
dirección del puntero sig del nodo.
Por lo que el parámetro reco recibe la dirección del segundo nodo.
Podemos observar como en las distintas llamadas recursivas el parámetro reco apunta
a un nodo. Cuando se van desapilando las llamadas recursivas se imprime
primeramente el 10 luego el 4 y por último el 5.
Problema 2:
Programa:
import java.io.File;
public class Recursividad{
Creamos un objeto de la clase File con el directorio que llega como parámetro y
mediante el método list obtenemos todos los archivos y directorios de dicho directorio:
for(int f=0;f<dir.length;f++){
if (ar2.isFile())
System.out.println(altura+dir[f]);
if (ar2.isDirectory()) {
System.out.println(altura +
"Directorio:"+dir[f].toUpperCase());
leer(inicio+dir[f]+"\\",altura+" ");
}
Si es un archivo lo mostramos y si es un directorio además de mostrarlo llamamos
recursivamente al método leer con el directorios nuevo a procesar.
Problema 3:
Desarrollar un programa que permita recorrer un laberinto e indique si tiene salida o no.
Para resolver este problema al laberinto lo representaremos con una matriz de 10 x 10
JLabel.
El valor:
Programa:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Laberinto extends JFrame implements ActionListener {
JLabel[][] l;
JButton b1;
JButton b2;
boolean salida;
Laberinto()
{
setLayout(null);
l=new JLabel[10][10];
for(int f=0;f<10;f++) {
for(int c=0;c<10;c++) {
l[f][c]=new JLabel();
l[f][c].setBounds(20+c*20,50+f*20,20,20);
add(l[f][c]);
}
}
b1=new JButton("Recorrer");
b1.setBounds(10,300,100,25);
add(b1);
b1.addActionListener(this);
b2=new JButton("Crear");
b2.setBounds(120,300,100,25);
add(b2);
b2.addActionListener(this);
crear();
}
public void crear()
{
for(int f=0;f<10;f++) {
for(int c=0;c<10;c++) {
int a=(int)(Math.random()*4);
l[f][c].setForeground(Color.black);
if (a==0)
l[f][c].setText("1");
else
l[f][c].setText("0");
}
}
l[9][9].setText("s");
l[0][0].setText("0");
}
if (l[fil][col].getText().equals("s"))
salida=true;
if (l[fil][col].getText().equals("0")) {
En caso de estar en el pasillo procedemos a fijar dicha JLabel con el caracter "9" e
intentamos desplazarnos en las cuatro direcciones (arriba, abajo, derecha e izquierda),
este desplazamiento lo logramos llamando recursivamente:
l[fil][col].setText("9");
l[fil][col].setForeground(Color.red);
recorrer(fil,col+1);
recorrer(fil+1,col);
recorrer(fil-1,col);
recorrer(fil,col-1);
Problemas propuestos
1. Desarrollar el juego del Buscaminas. Definir una matriz de 10*10 de JButton y
disponer una 'b' para las bombas (10 diez) un cero en los botones que no tienen
bombas en su perímetro, un 1 si tiene una bomba en su perímetro y así
sucesivamente. Cuando se presiona un botón si hay un cero proceder en forma
recursiva a destapar los botones que se encuentran a sus lados. Disponer el
mismo color de frente y fondo de los botones para que el jugador no pueda ver si
hay bombas o no.
Solución
Retornar
Listado completo de tutoriales
52 Estructuras dinámicas:
Conceptos de árboles
Igual que la lista, el árbol es una estructura de datos. Son muy eficientes para la
búsqueda de información. Los árboles soportan estructuras no lineales.
Grado de un nodo: es el número de nodos hijos que tiene dicho nodo (solo se tiene en
cuenta los nodos interiores)
Ej. El nodo A tiene grado 3.
El nodo B tiene grado 2.
Los otros nodos no tienen grado porque no tienen descendientes.
Árbol binario: Un árbol es binario si cada nodo tiene como máximo 2 descendientes.
Árbol binario ordenado: Si para cada nodo del árbol, los nodos ubicados a la
izquierda son inferiores al que consideramos raíz para ese momento y los nodos
ubicados a la derecha son mayores que la raíz.
Ej. Analicemos si se trata de un árbol binario ordenado:
Para el nodo que tiene el 50:
Los nodos del subárbol izquierdo son todos menores a 50? 8, 25, 30 Si
Los nodos del subárbol derecho son todos mayores a 50? 70 Si.
Para el nodo que tiene el 25:
Los nodos del subárbol izquierdo son todos menores a 25? 8 Si
Los nodos del subárbol derecho son todos mayores a 25? 30 Si.
No hace falta analizar los nodos hoja. Si todas las respuestas son afirmativas podemos
luego decir que se trata de un árbol binario ordenado.
Retornar
Listado completo de tutoriales
53 Estructuras dinámicas:
Inserción de nodos y recorrido de un árbol
binario
Insertamos el 400
Insertamos el valor 100. Debemos analizar si raíz es distinto a null verificamos si 100
es mayor o menor a la información del nodo apuntado por raíz, en este caso es menor
y como el subárbol izquierdo es null debemos insertarlo allí.
Insertamos el 200. Hay que tener en cuenta que siempre comenzamos las
comparaciones a partir de raíz. El 200 es menor que 400, descendemos por el subárbol
izquierdo. Luego analizamos y vemos que el 200 es mayor a 100, debemos avanzar
por derecha. Como el subárbol derecho es null lo insertamos en dicha posición.
Como podemos observar si cada vez que insertamos un nodo respetamos este
algoritmo siempre estaremos en presencia de un árbol binario ordenado.
Posteriormente veremos el algoritmo en java para la inserción de información en el
árbol.
Recorrer: Pasar a través del árbol enumerando cada uno de sus nodos una vez.
Visitar: Realizar algún procesamiento del nodo.
Pre-orden:
- Visitar la raíz.
- Recorrer el subárbol izquierdo en pre-orden.
- Recorrer el subárbol derecho en pre-orden.
Entre-orden
- Recorrer el subárbol izquierdo en entre-orden.
- Visitar la raíz.
- Recorrer el subárbol derecho en entre-orden.
Post-orden
- Recorrer el subárbol izquierdo en post-orden.
- Recorrer el subárbol derecho en post-orden.
- Visitar la raíz.
Ejemplo:
Veamos como se imprimen las informaciones de los nodos según su recorrido:
Recorrido preorden:
Es decir que el orden de impresión de la información es:
Recorrido entreorden:
Recorrido postorden:
Es decir que el orden de impresión de la información es:
Retornar
Listado completo de tutoriales
54 Estructuras dinámicas:
Implementación en Java de un árbol binario
ordenado
Problema 1:
Programa:
public ArbolBinarioOrdenado() {
raiz=null;
}
Creamos un nodo y disponemos los punteros izq y der a null, guardamos la información
que llega al método en el nodo.
Si el árbol está vacío, apuntamos raíz al nodo creado; en caso de no estar vacío,
dentro de una estructura repetitiva vamos comparando info con la información del
nodo, si info es mayor a la del nodo descendemos por el subárbol derecho en caso
contrario descendemos por el subárbol izquierdo.
Cuando se encuentra un subárbol vacío insertar el nodo en dicho subárbol. Para esto
llevamos un puntero anterior dentro del while.
El método recursivo void imprimirPre (Nodo reco) lo primero que verifica con un if si
reco está apuntando a un nodo (esto es verdad si reco es distinto a null), en caso
afirmativo ingresa al bloque del if y realiza:
- Visitar la raiz.
- Recorrer el subárbol izquierdo en pre-orden.
- Recorrer el subárbol derecho en pre-orden.
La visita en este caso es la impresión de la información del nodo y los recorridos son
las llamadas recursivas pasando las direcciones de los subárboles izquierdo y derecho.
Problema 2:
Confeccionar una clase que permita insertar un entero en un árbol binario ordenado
verificando que no se encuentre previamente dicho número.
Desarrollar los siguientes métodos:
1 Retornar la cantidad de nodos del árbol.
2 Retornar la cantidad de nodos hoja del árbol.
3 Imprimir en entre orden.
4 Imprimir en entre orden junto al nivel donde se encuentra dicho nodo.
5 Retornar la altura del árbol.
6 Imprimir el mayor valor del árbol.
7 Borrar el nodo menor del árbol.
public ArbolBinarioOrdenado() {
raiz=null;
}
}
}
}
Para imprimir todos los nodos en entre orden junto al nivel donde se encuentra
planteamos un método recursivo que llegue la referencia del nodo a imprimir junto al
nivel de dicho nodo. Desde el método no recursivo pasamos la referencia a raiz y un
uno (ya que raiz se encuentra en el primer nivel)
Cada vez que descendemos un nivel le pasamos la referencia del subárbol respectivo
junto al nivel que se encuentra dicho nodo:
Para imprimir el mayor valor del árbol debemos recorrer siempre por derecha hasta
encontrar un nodo que almacene null en der:
Retornar
Listado completo de tutoriales
56 Plugin WindowBuilder para crear
interfaces visuales.
El objetivo de este concepto es conocer el empleo del plugin WindowBuilder para el desarrollo de interfaces
visuales arrastrando componentes.
Desde la versión 3.7 de Eclipse llamada Indigo(2011) hasta la versión Mars(2015) se incorpora por defecto el
plugin WindowBuilder para la implementación de interfaces visuales.
Con esto ya tenemos instalado el WindowBuilder para trabajar en los siguientes conceptos.
A medida que uno arrastra componentes visuales sobre un formulario se genera en forma automática el código Java,
esto nos permite ser más productivos en el desarrollo de la interfaz de nuestra aplicación y nos ayuda a
concentrarnos en la lógica de nuestro problema.
1 Creación de un proyecto.
2 Seleccionamos el nombre de nuestro proyecto (lo llamaremos PruebaWindowBuilder):
3 Ahora seleccionamos la opción del menú File > New > Other ...
4 Seleccionamos la opción la opción JFrame:
5 Seguidamente presionamos el botón Next > y definimos el nombre de la clase a crear (Ventana1):
Tenemos en este momento nuestra aplicación mínima generada por el WindowBuilder. Podemos observar que
en la parte inferior de la ventana central aparecen dos pestañas (Source y Design) estas dos pestañas nos
permiten ver el código fuente de nuestro JFrame en vista de diseño o en vista de código Java:
Luego en vista de "Design":
6 Configuramos el Layout de JFrame presionando el botón derecho del mouse sobre el formulario generado y
seleccionamos la opción SetLayout > Absolute layout (esto nos permite luego disponer controles visuales como
JButton, JLabel etc. en posiciones fijas dentro del JFrame):
7 De la ventana Palette seleccionamos con el mouse un objeto de la clase JButton (presionamos con el mouse
dicha componente, deberá aparecer seleccionada) y luego nos desplazamos con el mouse sobre el JFrame y
presionamos el botón del mouse nuevamente ( en este momento aparece el botón dentro del JFrame):
En todo momento podemos cambiar la pestaña de "Source" y "Design" para ver el código generado. Por ejemplo
cuando agregamos el botón podemos ver que se agregó un objeto de la clase JButton al constructor:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Ventana1 frame = new Ventana1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Ventana1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
Si hacemos doble clic con el mouse en la pestaña Ventana1.java podemos maximizar el espacio de nuestro
editor visual (haciendo nuevamente doble clic vuelve al tamaño anterior)
Seleccionemos el primer JLabel de nuestro formulario y observemos las distintas partes que componen el plugin
WindowBuilder. En la parte superior izquierda se encuentra la sección "Structure" donde se muestran las
componentes visuales agregadas al formulario. Aparece resaltada la que se encuentra actualmente
seleccionada.
En la parte inferior aparece la ventana de "Properties" o propiedades del control visual
Veamos algunas propiedades que podemos modificar desde esta ventana y los cambios que se producen en el
código fuente en java.
La propiedad text cambia el texto que muestra el objeto JLabel. Probemos de disponer el texto "Ingrese nombre
de usuario:". De forma similar hagamos los cambios en la propiedad text de los otros controles visuales de
nuestro JFrame:
Si ahora seleccionamos la pestaña inferior para ver la vista de código java: "Source" podemos ver que el
WindowBuilder nos generó automáticamente el código para inicializar los textos de los controles JLabel y
JButton:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Ventana1 frame = new Ventana1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Ventana1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 203);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
Como podemos observar ahora cuando se crean los objetos de la clase JLabel en el constructor se inicializan
con los valores cargados en la propiedad text:
Problema propuesto 1
Crear la interfaz visual que aparece abajo. Inicializar las propiedades que corresponde.
Eventos
Para asociar eventos el plugin WindowBuilder nos proporciona una mecánica para automatizar la generación de
las interfaces que capturan los eventos de los objetos JButton, JMenuItem, JList etc.
Crearemos una interfaz visual similar a esta (tres controles de tipo JLabel, dos JTextField y un JButton):
Ahora seleccionamos el control JButton y en la ventana de propiedades presionamos el icono de la parte
superior:
Hacemos doble clic sobre la palabra performed y vemos que se abre el editor de texto y aparece el siguiente
código generado automáticamente:
btnSumar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
En el parámetro del método addActionListener del botón que suma se le pasa la referencia a una interface que
se crea de tipo ActionListener e implementa el método actionPerformed donde agregaremos el código necesario
para responder el evento.
Para este problema debemos rescatar los valores almacenados en los controles de tipo JTextField, convertirlos a
entero, sumarlos y enviar dicho resultado a una JLabel.
btnSumar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int v1=Integer.parseInt(textField.getText());
int v2=Integer.parseInt(textField_1.getText());
int suma=v1+v2;
lblResultado.setText(String.valueOf(suma));
}
});
Cuando compilamos vemos que no tenemos acceso al objeto lblResultado ya que está definido como una
variable local al constructor. Si queremos que se definan como atributos de la clase debemos seleccionar la
JLabel y presionar "convert Local to Field" (convertir de variable local a atributo de la clase):
Después de esto podemos acceder desde el método actionPerformed a la label.
Problema
Crear un menú de opciones que permita cambiar el color de fondo. Disponer un JMenuBar, un JMenu y 3 objetos
de la clase JMenuItem. Asociar los eventos respectivos para cada control de tipo JMenuItem.
La interfaz visual debe quedar similar a la siguiente:
Para crear esta interface debemos primero seleccionar la pestaña "Menu" donde se encuentran las
componentes relacionadas a la creación de menúes.
Debemos agregar (en este orden las siguientes componentes):
1 Un JMenuBar en la parte superior.
2 Un objeto de la clase JMenu en la barra del JMenuBar (podemos disponer el texto que queremos que se
muestre)
3 Agregamos un objeto de la clase JMenuItem en el sector donde aparece el texto: "Add items here". Los
mismos pasos hacemos para agregar los otros dos JMenuItem.
Ahora debemos asociar el evento clic para cado JMenuItem. Seleccionamos primero el control de tipo
JMenuItem y en la ventana de "Properties" presionamos el botón "Show events" y generamos el
actionPerformed para el JMenuItem seleccionado.
Luego codificamos:
mntmRojo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
contentPane.setBackground(Color.red);
}
});
Para cambiar el color del JFrame en realidad debemos modificar el color del JPanel que cubre el JFrame. El
objeto de la clase JPanel llamado contentPane tiene un método llamado setBackground que nos permite fijar el
color de fondo.
De forma similar asociamos los eventos para los otros dos objetos de la clase JMenuItem:
Retornar
56 Plugin WindowBuilder problemas Listado completo de tutoriales
resueltos
Problema 1
El funcionamiento es el siguiente:
Inicialmente el ascensor está en el piso 1.
Por ejemplo: si se presiona el botón 3 se muestra en un JLabel el piso número 3 y en otra JLabel
la dirección. La cadena "Sube", en caso de presionar un piso superior al actual. Mostramos la
cadena "Baja" en el JLabel si se presiona un piso inferior. y si el piso donde se encuentra
actualmente coincide con el presionado luego mostrar el mensaje "Piso actual".
1 Lo primero que debemos hacer cada vez que creamos un JFrame es definir el Layout a utilizar
(normalmente utilizaremos "Absolute Layout", esto lo hacemos presionando el botón derecho del
mouse dentro del JFrame y seleccionando la opción "Set Layout".
El tipo de layout a utilizar también se lo puede fijar seleccionando el objeto "contentPane"(este
objeto es de la clase JPanel y todo JFrame lo contiene como fondo principal) y luego en la ventana
de propiedades cambiamos la propiedad "Layot"
2 Cuando creamos el primer JButton definimos el nombre del objeto cambiando la propiedad
"Variable" y mediante la propiedad Text definimos el texto a mostrar (con el mouse dimensionamos
el JButton):
3 Los otros botones los podemos crear de la misma manera seleccionando un objeto de la clase
JButton de la "Palette" o cuando tenemos que crear otros objetos semejantes podemos presionar
el botón derecho del mouse sobre el objeto a duplicar y seguidamente en el menú contextual
seleccionar la opción "Copy" y seguidamente la opción "Paste" con lo que tendremos otro objeto
semejante.
Luego si deberemos definir un nombre para el objeto (propiedad "Variable") y la propiedad "text"
para la etiqueta a mostrar:
4 Los objetos que necesitemos consultar o modificar en tiempo de ejecución debemos definirlos
como atributos de clase (también llamados campos de clase)
En este problema cuando se presione alguno de los cuatro botones debemos consultar el
contendido de la label que indica el piso actual y la label que muestra la dirección será modificada
por otro String.
Para definir un control visual como atributo de clase debemos seleccionarlo y presionar en la
ventana de propiedades el botón "Convert local to field" (en nuetro problema definamos a estos
dos objetos de la clase JLabel con el nombre l1 y l2):
5 Para capturar el evento clic de un objeto de la clase JButton debemos seleccionarlo y presionar
el botón "Show Events":
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Create the frame.
*/
public Ascensor() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
l1 = new JLabel("1");
l1.setBounds(272, 41, 46, 14);
contentPane.add(l1);
l2 = new JLabel("baja");
l2.setBounds(272, 93, 92, 14);
contentPane.add(l2);
}
}
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int pisoactual=Integer.parseInt(l1.getText());
if (1<pisoactual)
l2.setText("Baja");
else
l2.setText("Piso actual");
l1.setText("1");
}
});
b4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int pisoactual=Integer.parseInt(l1.getText());
if (4>pisoactual)
l2.setText("Sube");
else
l2.setText("Piso actual");
l1.setText("4");
}
});
Si se presiona el botón del segundo piso debemos verificar si 2 es menor, mayor o igual al piso
actual (igual para el botón del tercer piso):
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int pisoactual=Integer.parseInt(l1.getText());
if (2<pisoactual)
if (2<pisoactual)
l2.setText("Baja");
else
if (2>pisoactual)
l2.setText("Sube");
else
l2.setText("Piso actual");
l1.setText("2");
}
});
Problema 2
Por un lado disponer tres objetos de la clase JRadioButton (llamarlos radio1, radio2 y radio 3),
configurar el primero para que aparezca seleccionado (propiedad "selected")
Disponer dos objetos de la clase JComboBox (llamarlos comboPesos y comboCentavos)
En el JComboBox pesos inicializar la propiedad model con los valores del 0 al 5 (hay que cargar
un valor por cada línea en el diálogo que aparece)
En forma similar el segundo JComboBox cargamos los valores: 0,10,20,30 etc. hasta 90.
Se sabe que :
Bebida A tiene un costo de 0 pesos 80 centavos.
Bebida B tiene un costo de 1 peso 20 centavos.
Bebida C tiene un costo de 3 pesos 10 centavos.
Solución:
Para que todos los JRadioButton estén asociados (es decir que cuando se seleccione uno se
deseleccione el actual lo debemos hacer en forma visual), primero seleccionamos con el mouse
todos los JRadioButton (para seleccionar varios controles presionamos la tecla "Ctrl" del teclado y
con el boton izquierdo del mouse seleccionamos los tres JRadioButton ) y seguidamente
presionamos el botón derecho del mouse y seleccionamos "New standard":
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JRadioButton;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.ButtonGroup;
public class PanelBebidas extends JFrame {
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PanelBebidas frame = new PanelBebidas();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public PanelBebidas() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 600, 319);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
}
});
b1.setBounds(30, 196, 89, 23);
contentPane.add(b1);
l1 = new JLabel("resultado");
l1.setBounds(148, 205, 73, 14);
contentPane.add(l1);
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int pesos=Integer.parseInt((String)comboPesos.getSelectedIt
int centavos=Integer.parseInt((String)comboCentavos.getSele
if (radio1.isSelected() && pesos==0 && centavos==80)
l1.setText("Correcto");
else
if (radio2.isSelected() && pesos==1 && centavos==20)
l1.setText("Correcto");
else
if (radio3.isSelected() && pesos==3 && centavos==10
l1.setText("Correcto");
else
l1.setText("Incorrecto");
}
});
Extraemos los contenidos de los dos controles de tipo JComboBox y los convertimos a entero.
Luego mediante tres if verificamos si el primer JRadioButton está seleccionado y el dinero
seleccionado corresponde a exactamente 0 pesos y 80 centavos, en tal caso mostramos en la
label el mensaje "Correcto". La lógica es similar para las otras dos bebidas.
Problema 3
Un embalse debe manejar la cantidad de mts3 de agua que pasa por cada compuerta. Por cada
compuerta puede pasar un caudal de 100 mts3 x seg.
Cuando presionamos el botón "Actualizar caudal" mostramos el nivel de caudal actual y un
mensaje que indica si el caudal es Bajo (0 a 100 mts3 x seg.) , Medio (> 100 200 mts3. x seg.) o
Alto (>200 mts3 x seg.)
Para la selección del caudal de cada compuerta utilizar componentes de tipo JSpinner.
El código fuente es:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JSpinner;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.SpinnerNumberModel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Embalse frame = new Embalse();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Embalse() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
l1 = new JLabel("resultado");
l1.setBounds(218, 203, 149, 14);
contentPane.add(l1);
}
}
En el evento clic del JButton extraemos los tres valores almacenados en los JSPinner:
int v1=Integer.parseInt(spinner1.getValue().toString());
int v2=Integer.parseInt(spinner2.getValue().toString());
int v3=Integer.parseInt(spinner3.getValue().toString());
y mediante tres if valuamos si la suma es menor o igual a 100 o menor o igual a 200 o en su
defecto es mayor a 200:
int suma=v1+v2+v3;
if (suma<=100)
l1.setText("Bajo");
else
if (suma<=200)
l1.setText("Medio");
else
l1.setText("Alto");
Problema propuesto
1. Implementar un programa para la extracción de dinero de un cajero automático.
Se debe poder fijar la cantidad de dinero a extraer:
Disponer un control de tipo JComboBox (disponer los valores: 0,50,150 etc. hasta 500)
Por otro lado poder seleccionar el tipo de cuenta (almacenar en otro JComboBox los
textos "Caja de Ahorro" y "Cuenta Corriente".
Se debe tener en cuenta que:
De Caja de Ahorro se puede extraer hasta 200.
De Cuenta Corriente se puede extraer hasta 400.
Al presionar el botón extraer mostrar en una label el texto "correcto" si para el tipo de
cuenta el importe está permitido.
Inicialmente el cajero tiene almacenado un monto de 3000 pesos. Restar en cada
extracción el monto respectivo y mostrar el mensaje ?fuera de servicio? cuando se intenta
extraer más del dinero que hay en el cajero.
Retornar
Listado completo de tutoriales
57 Clase Graphics y sus
métodos
Java proporciona la clase Graphics, que permite dibujar elipses, cuadrados, líneas,
mostrar texto y también tiene muchos otros métodos de dibujo. Para cualquier
programador, es esencial el entendimiento de la clase Graphics, antes de adentrarse
en el dibujo en Java.
La clase Graphics proporciona el entorno de trabajo para cualquier operación gráfica
que se realice dentro del AWT.
Para poder pintar, un programa necesita un contexto gráfico válido, representado por
una instancia de la clase Graphics. Pero esta clase no se puede instanciar
directamente; así que debemos crear un componente y pasarlo al programa como un
argumento al método paint().
El único argumento del método paint() es un objeto de esta clase. La clase Graphics
dispone de métodos para soportar tres categorías de operaciones gráficas:
1) Dibujo de primitivas gráficas,
2) Dibujo de texto,
3) Presentación de imágenes en formatos *.gif y *.jpeg.
Problema 1
Crear una aplicación que utilice las primitivas gráficas principales que provee la clase
Graphics:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grafico1 frame = new Grafico1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Grafico1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
setBounds(0,0,800,600);
}
g.setColor (Color.blue);
g.drawLine (0, 70, 100, 70);
g.drawRect (150, 70, 50, 70);
g.drawRoundRect (250, 70, 50, 70, 6, 6);
g.drawOval (350, 70, 50, 70);
int [] vx1 = {500, 550, 450};
int [] vy1 = {70, 120, 120};
g.drawPolygon (vx1, vy1, 3);
g.setColor (Color.red);
g.fillRect (150, 270, 50, 70);
g.fillRoundRect (250, 270, 50, 70, 6, 6);
g.fillOval (350, 270, 50, 70);
int [] vx2 = {500, 550, 450};
int [] vy2 = {270, 320, 320};
g.fillPolygon (vx2, vy2, 3);
}
}
El método paint se ejecuta cada vez que el JFrame debe ser redibujado y llega como
parámetro un objeto de la clase Graphics. Este objeto nos permite acceder al fondo del
JFrame y utilizando las primitivas gráficas dibujar líneas, rectángulos, elipses etc.
Lo primero que hacemos dentro de este método es llamar al método paint de la clase
superior para que se pinte el fondo del JFrame y otras componentes contenidas dentro
(para llamar al método paint de la clase JFrame debemos anteceder la palabra clave
super y pasar el parámetro respectivo):
super.paint(g);
g.setColor (Color.blue);
Dibuja una línea desde la coordenada (0,70) es decir columna 0 y fila 70 en píxeles,
hasta la coordenada (100,70). La línea es de color azul:
g.drawLine (0, 70, 100, 70);
Dibujamos un óvalo:
Dibujamos un triángulo (debemos indicar mediante dos vectores los vértices de cada
punto del triángulo), el primer punto es el (500,70) el segundo punto es el (550,120) y
por último el punto (450,120):
De forma similar los métodos fillRect, fillRoundRect, fillOval y fillPolygon son similares a
los anteriores con la diferencia que pinta su interior con el color activo de la última
llamada al método setColor:
g.setColor (Color.red);
g.fillRect (150, 270, 50, 70);
g.fillRoundRect (250, 270, 50, 70, 6, 6);
g.fillOval (350, 270, 50, 70);
int [] vx2 = {500, 550, 450};
int [] vy2 = {270, 320, 320};
g.fillPolygon (vx2, vy2, 3);
Dibujar texto
La clase Graphics permite ?dibujar? texto, como alternativa al texto mostrado en los
componentes JLabel, JTextField y JTextArea. El método que permite graficar texto
sobre el JFrame es:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grafico1 frame = new Grafico1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Grafico1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
setBounds(0,0,800,600);
}
}
Clase Color
Problema 3
Crear una aplicación que dibuje 255 líneas creando un color distinto para cada una de
ellas:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grafico1 frame = new Grafico1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Grafico1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
setBounds(0,0,800,255);
}
int fila = 0;
for (int rojo = 0 ; rojo <= 255 ; rojo++)
{
Color col = new Color (rojo, 0, 0);
g.setColor (col);
g.drawLine (0, fila, 800, fila);
fila++;
}
Presentación de imágenes
Clase Image
Una imagen es un objeto gráfico rectangular compuesto por pixels coloreados. Cada
pixel en una imagen describe un color de una particular localización de la imagen.
A continuación, algunos métodos de la clase Image:
La clase Graphics provee el método drawImage() para dibujar imagenes; este método
admite varias formas:
Problema 4
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grafico1 frame = new Grafico1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Grafico1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
setBounds(0,0,800,600);
}
Por último llamamos al método drawImage con la referencia al objeto de tipo Image, la
columna, la fila y la referencia al JFrame donde debe dibujarse:
Método repaint()
Este es el método que con más frecuencia es llamado por el programador. El método
repaint() llama ?lo antes posible? al método paint() del componente.
El método repaint() puede ser:
repaint()
repaint(int x, int y, int w, int h)
Las segunda forma permiten definir una zona rectangular de la ventana a la que aplicar
el método.
Problema 5
Crear una aplicación que muestre un círculo en medio de la pantalla y mediante dos
botones permitir que se desplace a izquierda o derecha.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Launch the application.
*/
/**
* Create the frame.
*/
public Grafico1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
bi.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
columna=columna-10;
repaint();
}
});
El método paint dibuja un círculo utilizando como posición el valor del atributo columna:
Problema 6
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JSpinner;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ProcesadorTexto extends JFrame {
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ProcesadorTexto frame = new ProcesadorTexto();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public ProcesadorTexto() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 573, 481);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
sp2.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
repaint();
}
});
g.setColor(Color.blue);
g.drawRect(30,80,100,140);
Extraemos los valores seleccionados de cada control JSpinner y los convertimos a tipo
entero:
int ms=Integer.parseInt(sp1.getValue().toString());
int mi=Integer.parseInt(sp2.getValue().toString());
Activamos el color rojo y dibujamos las dos líneas, la superior coincide con el comienzo
del rectángulo (sumamos tantos pixeles en la fila como lo indica el primer JSpinner):
g.setColor(Color.red);
g.drawLine(30,80+ms,130,80+ms);
g.drawLine(30,220-mi,130,220-mi);
String direccion=(String)comboBox.getSelectedItem();
if (direccion.equals("Horizontal"))
g.drawRect(320,120,200,100 );
else
g.drawRect(320,120,100,200 );
Por último cuando se presiona el botón inicializar procedemos a fijar nuevos valores a
los JSpinner y al JComboBox (luego redibujamos):
btnInicializar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
sp1.setValue(0);
sp2.setValue(0);
comboBox.setSelectedIndex(0);
repaint();
}
});
Problemas propuestos
1. Confeccionar un programa que permita configurar las características del
mouse.
Por un lado debemos seleccionar la velocidad de desplazamiento de la flecha
del mouse. Disponer un JSpinner para poder seleccionarse los valores
0,25,50,75 y 100.
Por otro lado debemos poder seleccionar cual de los dos botones del mouse
será el principal, tenemos para esta función un JComboBox con dos opciones:
izquierdo o derecho.
Cuando se selecciona el botón (cambio en el JComboBox) actualizar el gráfico
mostrando el botón del mouse seleccionado (graficar en el método paint el
mouse en pantalla)
2. En una aduana hay una máquina que sortea las personas cuyo equipaje serán
revisados.
La persona selecciona si viene del Interior del país o del Exterior (a través de
un JComboBox), y por otro lado selecciona la cantidad de bultos (JSpinner).
Luego presiona el botón sortear y aparece al lado de este botón un círculo rojo
o verde. (En caso de ser rojo se revisa su equipaje, en caso de ser verde, no
se revisa)
Para el sorteo generar un valor aleatorio entre 1 y 3. Si se genera un 1 se
revisa, si se genera un 2 o 3 no se revisa.
Validar que también este seleccionado un valor distinto a cero en bultos (los
valores pueden ir de 0 a 10).
Si la cantidad de bultos supera a 5 se revisa siempre sus bultos (es decir que
aparece un círculo rojo).
Luego de sortear fijar en cero cantidad de bultos.
Mostrar en el título del JFrame la cantidad de bultos revisados y no revisados
hasta el momento.
Retornar
Listado completo de tutoriales
58 Gráficos estadísticos
Problema 1
Crear una aplicación que solicite el ingreso de tres valores por teclado que representan
las cantidades de votos obtenidas por tres partidos políticos. Luego mostrar un gráfico
de tartas:
El algorítmo es:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax swing JLabel;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GraficoTarta frame = new GraficoTarta();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GraficoTarta() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 600);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
g.setColor(new Color(255,0,0));
g.fillArc(50,250,200,200,0,grados1);
g.fillRect(370,250,20,20);
g.drawString("Partido 1", 400, 270);
g.setColor(new Color(0,128,0));
g.fillArc(50,250,200,200,grados1,grados2);
g.fillRect(370,280,20,20);
g.drawString("Partido 2", 400, 300);
g.setColor(new Color(0,0,255));
g.fillArc(50,250,200,200,grados1+grados2,grados3);
g.fillRect(370,310,20,20);
g.drawString("Partido 1", 400, 330);
}
}
El atributo bandera se inicializa cuando se define con el valor false, esto hace que
cuando se ejecute por primera vez el método paint no ingrese al if:
Se definen tres objetos de la clase JTextField para ingresar los tres valores por teclado:
Cuando se presiona el botón se cambia el estado del atributo bandera por el valor true
y se llama al método repaint (recordemos que este método borra el JFrame y llama al
método paint para que ahora dibuje el gráfico de tarta):
btnGraficar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
bandera=true;
repaint();
}
});
Lo primero que hacemos para graficar la tarta es rescatar los tres valores ingresados
en los controles JTextField:
if (bandera==true)
{
String s1=tf1.getText();
String s2=tf2.getText();
String s3=tf3.getText();
int v1=Integer.parseInt(s1);
int v2=Integer.parseInt(s2);
int v3=Integer.parseInt(s3);
int suma=v1+v2+v3;
Seguidamente calculamos los grados que le corresponde a cada trozo de tarta
(teniendo en cuenta que tenemos 360 grados para repartir):
Cada trozo de tarta lo obtenemos mediante la ecuación:
tamaño trozo= cantidad de votos del partido/ total de votos * 360
si observamos la ecuación podemos imaginar que la división:
cantidad de votos del partido / total de votos
generará un valor menor a uno (salvo que el partido haya obtenido todos los votos de
la elección en cuyo caso la división genera el valor uno)
Esta división nos genera el porcentaje de votos que le corresponde al partido y luego
dicho porcentaje lo multiplicamos por la cantidad de grados a repartir (que son 360
grados)
Luego como la división generará un valor menor a uno y al tratarse de dos variables
enteras el resultado será cero. Para evitar este problema procedemos primero a
multiplicar por 360 y luego dividir por la variable suma:
int grados1=v1*360/suma;
int grados2=v2*360/suma;
int grados3=v3*360/suma;
int grados1=(int)((float)v1/suma*360);
int grados2=(int)((float)v2/suma*360);
int grados3=(int)((float)v3/suma*360);
Procedemos ahora a graficar los trozos de tarta y leyenda con el valor ingresado
(activamos el color rojo y mediante el método fillArc creamos un trozo de tarta que se
inicia en el grado 0 y avanza tantos trados como indica la variable grados1. Luego
mediante el método drawString mostramos la leyenda del partido respectivo con un
cuadradito también de color rojo ):
g.setColor(new Color(255,0,0));
g.fillArc(50,250,200,200,0,grados1);
g.fillRect(370,250,20,20);
g.drawString("Partido 1", 400, 270);
tC l ( C l (0 128 0))
g.setColor(new Color(0,128,0));
g.fillArc(50,250,200,200,grados1,grados2);
g.fillRect(370,280,20,20);
g.drawString("Partido 2", 400, 300);
g.setColor(new Color(0,0,255));
g.fillArc(50,250,200,200,grados1+grados2,grados3);
g.fillRect(370,310,20,20);
g.drawString("Partido 1", 400, 330);
Problema 2
Crear una aplicación que solicite el ingreso de tres valores por teclado que representan
las cantidades de votos obtenidas por tres partidos políticos. Luego mostrar un gráfico
de barras horizontales:
El algorítmo es:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
i j i b d d
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GraficoBarraHorizontal frame = new
GraficoBarraHorizontal();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GraficoBarraHorizontal() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 600);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
int largo1=v1*400/mayor;
int largo2=v2*400/mayor;
int largo3=v3*400/mayor;
g.setColor(new Color(255,0,0));
g.fillRect(100,250,largo1,40);
g.drawString("Partido 1", 10, 270);
g.setColor(new Color(0,128,0));
g.fillRect(100,300,largo2,40);
g.drawString("Partido 2", 10, 320);
g.setColor(new Color(0,0,255));
g.fillRect(100,350,largo3,40);
g.drawString("Partido 3", 10, 370);
}
}
int mayor=retornarMayor(v1,v2,v3);
int largo1=v1*400/mayor;
Como podemos ver primero multiplicamos por 400 y lo dividimos por el mayor de los
tres valores ingresados.
Nuevamente primero multiplicamos y luego dividimos con el objetivo que el resultado
de la división no nos redondee a cero.
El primer trozo lo graficamos a partir de la columna 100, fila 250 y con un ancho
indicado en la variable largo1 (el alto de la barra es de 40 píxeles):
g.setColor(new Color(255,0,0));
g ( ( , , ));
g.fillRect(100,250,largo1,40);
g.drawString("Partido 1", 10, 270);
g.setColor(new Color(0,128,0));
g.fillRect(100,300,largo2,40);
g.drawString("Partido 2", 10, 320);
g.setColor(new Color(0,0,255));
g.fillRect(100,350,largo3,40);
g.drawString("Partido 3", 10, 370);
Problema propuesto
1. Implementar un gráfico estadístico de tipo "Barra Porcentual":
Solución
Retornar
Listado completo de tutoriales
59 JDBC con MySQL
JDBC son las siglas en ingles de Java Database Connectivity. Es un conjunto de clases que nos permite acceder a
diversos gestores de bases de datos en forma transparente.
Utilizaremos esta herramienta en lugar de descargar solo el MySQL con la finalizar de facilitar la instalación y
configuración del motor de base de datos (la instalación de esta herramienta es sumamente sencilla), además
utilizaremos otra software que provee el WampServer que es el PhpMyAdmin que nos facilitará la creación de la base
de datos.
Luego de instalarse nos solicita que navegador abrirá por defecto cuando ejecutemos el PhpMyAdmin (para la creación
de la base de datos de MySQL):
En el siguiente diálogo dejamos los datos por defecto:
Finalmente aparece el diálogo final donde se nos informa que se iniciará el WampServer (es decir que se cargará en
memoria entre otras cosas el MySQL) :
Ahora podemos ver el iconos del WampServer en la bandeja del sistema de Windows (si se encuentra en color verde
significa que el MySQL está ejecutándose correctamente):
Haciendo clic sobre el ícono de la bandeja del sistema aparece un menú que nos permite lanzar el PhpMyAdmin para
crear la base de datos de MySQL:
El PhpMyAdmin es un programa web que nos permite administrar las bases de datos del MySQL:
Seleccionamos la pestaña "Base de datos" y donde dice "Crear nueva base de datos" especificamos que nuestra base
de datos se llamará "bd1":
Presionamos el botón "crear" y con esto ya tenemos nuestra base de datos creada:
Luego de seleccionar la base de datos "bd1" que figura a la izquierda procedemos a crear la primer tabla que
contendrá (crearemos una tabla llamada "articulos" y que tendrá tres campos):
En la tabla "articulos" definimos el campo "codigo" de tipo int (este campo será el "primary key" y auto_increment lo
tildamos para que el código se genere automáticamente), el segundo campo es la descripción que es de tipo varchar
con un máximo de 50 caracteres y por último el campo precio que es de tipo float.
Luego de especificar los tres campos en la parte inferior de la misma ventana aparece un un botón llamada "Guardar"
para confirmar la estructura de la tabla:
En el lado izquierdo del navegador podemos ver ahora que la base de datos "bd1" tiene una tabla llamada "articulos"
Hasta acá lo que nos ayuda el PhpMyAdmin (es decir creación de la base de datos y la tabla), de ahora en más todas
las otras actividades las desarrollaremos desde nuestro programa en java (poblar o insertar datos, listar registros,
consultar, modificar y borrar datos)
Descarga del Driver para permitir conectar nuestro programa Java con el MySQL
Como última actividad de configuración previo a implementar los programas en Java para acceder a MySQL es la
descarga del Driver que nos permita conectarnos con la base de datos.
Podemos descomprimir el archivo mysqlconnectorjava5.1.18.zip que acabamos de descargar. Luego veremos que
en nuestro programa en java haremos referencias al archivo mysqlconnectorjava5.1.18bin.jar (que es el Driver
propiamente dicho)
Retornar
Listado completo de tutoriales
60 Alta y Consulta de una tabla de
MySQL
Problema 1
Ya creamos en el concepto anterior una base de datos llamada bd1 y en la misma creamos una
tabla llamada articulos.
Procederemos a implementar en Java un programa que nos permita comunicarnos con la base
de datos "bd1" e insertar filas en la tabla "articulos" y posteriormente consultar su contenido.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Formulario frame = new Formulario();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Formulario() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 606, 405);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
Tenemos una clase llamada "Class" que tiene un método estático llamado forName, al mismo
hay que pasar el nombre de la clase a importar:
Class.forName("com.mysql.jdbc.Driver");
com.mysql.jdbc es el nombre del paquete donde se encuentra la clase Driver. Esta el la forma
que importamos los driver en Java.
El método forName de la clase Class genera excepciones de tipo Excepcion que deben ser
capturadas obligatoriamente (luego por eso encerramos el código en un bloque try/catch.
...........
tf3 = new JTextField();
tf3.setBounds(247, 176, 86, 20);
contentPane.add(tf3);
tf3.setColumns(10);
cargarDriver();
}
Todas las clases orientadas al acceso a base de datos generan excepciones de tipo
SQLException y deben ser capturadas obligatoriamente. Lo primero que hacemos es crear un
objeto de la clase Connection, para esto la clase DriverManager tiene un método llamado
getConnection que retorna un objeto de la clase Connection:
Connection
conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");
El método getConnection debemos pasarle tres String, el primero indica el nombre de la base
de datos que queremos acceder (en este caso "bd1"), el segundo parámetro es el nombre de
usuario (recordemos que cuando instalamos el MySQL se crea un usuario por defecto llamado
"root") y el último parámetro el la clave del usuario "root", por defecto esta clave es un String
vacío.
Como podemos ver también previo a la base de datos tenemos en la cadena de conexión el
nombre de nuestro servidor (localhost)
Si nos equivocamos por ejemplo con el nombre de base de datos a comunicarnos (por ejemplo
cambiar "bd1" por "bdx") veremos en el título del JFrame el mensaje de error que nos devuelve
el MySQL:
Luego creamos un objeto de la clase Statement a partir del objeto de la clase Connection que
acabamos de crear:
Statement comando=conexion.createStatement();
La clase Statement tiene un método llamado executeUpdate que le pasamos el comando SQL
insert para agregar una fila a la tabla articulos:
Como podemos ver generamos el String con el comando insert rescatando los datos de los dos
controles de tipo JTextField. Es importante notar que en Java los String están encerrados entre
comillas dobles y los contatenamos con el operador +. Las comillas simples son necesarias
para los campos de tipo varchar de MySql (como podemos notar el lugar donde se dispondrá el
texto de la descripción del artículo deben ir obligatoriamente las comillas simples):
...'"+tf1.getText()+"'...
Si nos olvidamos las comillas simples al generar el String con el comando Insert el MySQL nos
devolverá un error que será capturado por el try/catch, por ejemplo si lo ejecutamos con la
siguiente sintaxis (sin las comillas simples envolviendo el valor de la descripción):
Luego de solicitar la ejecución del comando Insert al MySQL procedemos a llamar al método
close de la clase Connection:
conexion.close();
Con lo visto ya podemos agregar filas a la tabla articulos. Veamos ahora como consultar datos.
El código a implementar cuando se presiona el botón "Consulta por código" es el siguiente:
tf1.setText(registro.getString("descripcion"));
tf2.setText(registro.getString("precio"));
} else {
labelResultado.setText("No existe
un artículo con dicho código");
}
conexion.close();
} catch(SQLException ex){
setTitle(ex.toString());
}
}
});
De forma similar al Insert procedemos a crear un objeto de la clase Connection y otro objeto de
la clase Statement:
Connection
conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");
Statement
comando=conexion.createStatement();
ResultSet registro =
comando.executeQuery("select descripcion,precio from articulos where
codigo="+tf3.getText());
La clase ResultSet lo podemos imaginar como una tabla con todos los datos recuperados del
comando SQL select que acaba de ejecutar el MySQL. En este ejemplo puede retornar una fila
o ninguna ya que estamos utilizando la cláusula where y preguntando por el campo clave
codigo.
Para acceder al registro devuelto debemos llamar al método next(), si retorna true es que si se
recuperó una fila de la tabla articulos (es decir si existe el codigo de articulo ingresado), en
caso que retorne false el método next() significa que no hay un artículo con el código que
ingresamos en el control JTextField:
if (registro.next()==true) {
tf1.setText(registro.getString("descripcion"));
tf2.setText(registro.getString("precio"));
} else {
labelResultado.setText("No existe
un artículo con dicho código");
}
Retornar
Listado completo de tutoriales
61 Baja y modificación de datos de
una tabla de MySQL
Problema 1
Ya creamos anteriormente una base de datos llamada bd1 y en la misma creamos una tabla
llamada articulos.
Procederemos a implementar en Java un programa que nos permita comunicarnos con la base
de datos "bd1" y consultar, borrar y modificar filas en la tabla "articulos".
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Formulario frame = new Formulario();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Formulario() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 606, 405);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
tf1.setText(registro.getString("descripcion"));
tf2.setText(registro.getString("precio"));
} else {
labelResultado.setText("No existe
un artículo con dicho código");
}
conexion.close();
} catch(SQLException ex){
setTitle(ex.toString());
}
}
});
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
labelResultado.setText("");
try {
Connection
conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");
Statement comando=conexion.createStatement();
int cantidad = comando.executeUpdate("delete from articulos where
codigo="+tf3.getText());
if (cantidad==1) {
tf1.setText("");
tf2.setText("");
labelResultado.setText("Se borro el artículo con dicho código");
} else {
labelResultado.setText("No existe un artículo con dicho código");
}
conexion.close();
} catch(SQLException ex){
setTitle(ex.toString());
}
}
});
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
labelResultado.setText("");
try {
Connection
conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");
Statement comando=conexion.createStatement();
int cantidad = comando.executeUpdate("update articulos set
descripcion='" + tf1.getText() + "'," +
"precio=" + tf2.getText() + " where
codigo="+tf3.getText());
if (cantidad==1) {
labelResultado.setText("Se modifico la descripcion y el precio del
artículo con dicho código");
} else {
labelResultado.setText("No existe un artículo con dicho código");
}
conexion.close();
} catch(SQLException ex){
setTitle(ex.toString());
}
}
});
Es importante notar las comillas simples luego del caracter =, esto debido a que se trata de un
campo de tipo varchar.
Retornar
Listado completo de tutoriales
62 Instalación del "Eclipse IDE for Java
EE Developers" y el servidor "Apache Tomcat"
La versión que debemos descargar es Eclipse IDE for Java EE Developers, como podemos ver el tamaños
es mayor que la versión que hemos utilizado hasta este momento (Eclipse IDE for Java Developers)
Podemos crear otra carpeta con otro nombre para no perder la versión de Eclipse que hemos utilizado para
el desarrollo de aplicaciones de escritorio (swing)
Creemos la carpeta eclipsej2ee y dentro de la misma descomprimamos el entorno de Eclipse que acabamos
de descargar "Eclipse IDE for Java EE Developers".
Cuando ejecutamos el Eclipse nos pide seleccionar la carpeta donde se almacenarán los proyectos que
crearemos y aparece el siguiente entorno (como podemos ver prácticamente igual que la versión "Java
Developers" con un título distinto):
Pero si ingresamos al menú de opciones File > New veremos que nos permite crear una serie de proyectos
muy distintos a la otra versión de Eclipse:
"Apache Tomcat"
Ahora pasaremos a instalar un servidor web "Apache Tomcat" que nos permitirá ejecutar servlet y páginas
dinámicas.
Podemos descargar el "Apache Tomcat" de aquí (descargar el archivo Binary Distributions Core 32bit
Windows zip) y descomprimirlo en una carpeta.
Una vez descomprimido procedemos a registrarlo en Eclipse. Desde el menú de opciones seleccionamos
Window > Preferences y en el diálogo que aparece debemos seleccionar Server > Runtimes Environments
y presionar el botón "Add...":
En el nuevo diálogo que aparece seleccionamos de la carpeta "Apache" la versión 7 que es la que
acabamos de descargar y descomprimir en una carpeta de nuestro disco duro:
En el último diálogo que aparece debemos seleccionar la carpeta donde hemos descomprimido el "Apache
Tomcat" y presionar el botón "Finish:
Ahora debemos iniciar los servicios del servidos "Apache Tomcat" para podes hacer aplicaciones que hagan
peticiones.
Para arrancar el Tomcat debemos presionar el botón derecho del mouse sobre la ventana "Server", si no
parece esta ventana podemos activarla desde el menú (Window > Show View > Servers) y seguidamente
seleccionar del menú contextual la opción New > Server:
En este diálogo seleccionamos "Apache" Tomcat V7.0 y presionamos el botón "Finish":
Como podemos ver ya tenemos el "Tomcat" listo para poderlo utilizar en los distintos proyectos que
implementaremos:
Retornar
Listado completo de tutoriales
63 Servlet
Un servlet es una clase que se ejecuta en el contexto de un servidor web (en nuestro caso el Apache Tomcat)
Un servlet se ejecuta en un servidor web y el resultado de ejecución viaja por internet para ser visualizado en
un navegador web (normalmente un servlet genera HTML, pero puede generar otros formatos de archivos)
Veremos los pasos en Eclipse para crear un servlet mínimo que nos muestre un mensaje y los números del 1
al 10000.
Desde el menú de opciones seleccionamos File > New > Dynamic Web Project:
En el diálogo siguiente especificamos el nombre del proyecto (en nuestro caso le llamaremos
proyectoservlet1) y presionamos el botón "Finish":
El Eclipse nos crea una serie de carpetas y archivos donde alojaremos los servlet:
Ahora presionamos el botón derecho sobre el nombre del proyecto y seleccionamos la opción New >
Servlet:
En el diálogo siguiente especificamos el nombre de nuestro servlet (en nuestro ejemplo le llamaremos
HolaMundo), presionamos el botón "Finish" y ya tenemos el esqueleto básico de un servlet:
/**
* Servlet implementation class HolaMundo
*/
@WebServlet("/HolaMundo")
public class HolaMundo extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HolaMundo() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
Todo servlet debe heredar de la clase HttpServlet que se encuentra en el paquete javax.servlet.http
Esta clase debe sobreescribir el método doGet o doPost (o ambos) En el protocolo HTTP las peticiones
pueden ser de tipo post (cuando llamamos a una página desde un formulario HTML) y de tipo get (páginas
sin formulario)
Nuestro problema es mostrar un mensaje e imprimir los números del 1 al 10000, esta actividad la haremos en
el método doGet.
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HolaMundo
*/
@WebServlet("/HolaMundo")
public class HolaMundo extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HolaMundo() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head></head>");
out.println("<body>");
out.println("<h1>Hola Mundo</h1>");
for(int f=1;f<=10000;f++) {
out.println(f);
out.println(" - ");
}
out.println("</body>");
out.println("</html>");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
// TODO Auto-generated method stub
}
Una parte importante de la declaración del servlet que nos genera automáticamente el Eclipse es la
anotación @WebServlet (esta línea registra el servlet para todas las peticiones al servidor con la sintaxis
http://localhost:8080/proyectoservlet1/HolaMundo):
@WebServlet("/HolaMundo")
Obtenemos una referencia de un objeto de la clase PrintWriter (debemos importar la clase PrintWriter)
mediante la llamada al método getWriter del objeto response que llega como parámetro al método doGet:
Todas las salidas son llamando al método println del objeto out de la clase PrintWriter. Como vemos
generamos como salida HTML, para mostrar los números del 1 al 10000 es más conveniente utilizar una
estructura repetitiva que hacer una salida secuencial.
Para probar el servlet que acabamos de codificar debemos presionar el botón derecho del mouse sobre el
nombre de la clase y seleccionar "Run on Server":
Aparece un diálogo que debemos seleccionar el botón "Finish" ya que está seleccionado el servidor "Tomcat"
para ejecutar el servlet:
El resultado de la ejecución del servlet lo podemos ver dentro de una ventana dentro del mismo Eclipse:
Si queremos que el resultado aparezca en otro navegador podemos configurar desde el menú de Eclipse el
navegador que muestra el resultado que devuelve Tomcat:
Retornar
Listado completo de tutoriales
64 Recuperación de los datos de un
formulario HTML en un servlet
En el diálogo siguiente especificamos el nombre del archivo html, en nuestro caso lo llamaremos
formulario1.html:
Codificamos la página html con el formulario web que solicita el ingreso del nombre de usuario y su
clave:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class RecuperacionUsuario
*/
@WebServlet("/RecuperacionUsuario")
public class RecuperacionUsuario extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public RecuperacionUsuario() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head></head>");
out.println("<body>");
out.println("Usuario:");
String usu=request.getParameter("usuario");
out.println(usu);
out.println("<br>");
out.println("Clave:");
String cla=request.getParameter("clave");
out.println(cla);
out.println("</body>");
out.println("</html>");
}
Como podemos ver en el código fuente de la clase RecuperacionUsuario debemos implementar todo
el código en el método doPost, ya que este se ejecuta cuando se tiene un formulario HTML y se
especificó en el HTML en la propiedad method el valor post:
<form method="post" action="RecuperacionUsuario">
Para recuperar los datos de los controles text y password del formulario HTML el objeto request de la
clase HttpServletRequest dispone de un método llamado getParamenter que le indicamos el nombre
del control a recuperar:
String usu=request.getParameter("usuario");
out.println(usu);
Para probar nuestra aplicación debemos presionar el botón derecho sobre el formulari1.html y
seleccionar "Run As" > "Run on Server", luego el resultado de la ejecución en el navegador:
Problema propuesto
1. Crear un proyecto llamado proyectoservlet3. Confeccionar un formulario HTML que solicite la
carga de 2 valores por teclado. Cuando se presione el botón submit llamar a un servlet que
recupere los dos valores ingresados y muestre su suma.
Solución
Retornar
65 Llamada a servlet desde un Listado completo de tutoriales
hipervínculo (con y sin parámetros)
Problema:
Confeccionaremos una página HTML con dos hipervínculos a dos servlet. El primero
tiene por objetivo mostrar la tabla de multiplicar del 2, el segundo servlet llega como
parámetro el número del cual queremos mostrar la tabla de multiplicar.
El segundo hipervínculo llama al servlet Tabla y pasa un parámetro num con el valor 5 (este valor se
rescatará posteriormente desde el servlet):
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class TablaDel2
*/
@WebServlet("/TablaDel2")
public class TablaDel2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TablaDel2() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head></head>");
out.println("<body>");
out.println("<h1>Tabla del 2</h1>");
for(int f=2;f<=20;f=f+2) {
out.println(f);
out.println(" - ");
}
out.println("</body>");
out.println("</html>");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
Es importante hacer notar que la anotación del servlet coincide con la propiedad href del hipervínculo
de la página HTML:
@WebServlet("/TablaDel2")
public class TablaDel2 extends HttpServlet {
out.println("<html>");
out.println("<head></head>");
out.println("<body>");
out.println("<h1>Tabla del 2</h1>");
for(int f=2;f<=20;f=f+2) {
out.println(f);
out.println(" - ");
}
out.println("</body>");
out.println("</html>");
}
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Tabla
*/
@WebServlet("/Tabla")
public class Tabla extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Tabla() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head></head>");
out.println("<body>");
String cad=request.getParameter("num");
int valor=Integer.parseInt(cad);
out.println("<h1>Tabla del "+cad+"</h1>");
for(int f=valor;f<=valor*10;f=f+valor) {
out.println(f);
out.println(" - ");
}
out.println("</body>");
out.println("</html>");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
Para recuperar el parámetro del hipervínculo llamamos al método getParameter del objeto request.
Debemos pasar un String con el nombre del parámetro y el mismo nos retorna el valor del parámetro:
String cad=request.getParameter("num");
Retornar
Listado completo de tutoriales
66 Redireccionamiento a otro
sitio o página desde un servlet
Problema:
Como vemos cuando se presiona el botón submit se envían los datos al servlet llamado
Redireccionamiento:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Redireccionamiento
*/
@WebServlet("/Redireccionamiento")
public class Redireccionamiento extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Redireccionamiento() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request,
HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
String dire=request.getParameter("direccion");
response.sendRedirect("http://"+dire);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request,
HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
Retornar